86#define DEBUG_TYPE "dagcombine"
88STATISTIC(NodesCombined ,
"Number of dag nodes combined");
89STATISTIC(PreIndexedNodes ,
"Number of pre-indexed nodes created");
90STATISTIC(PostIndexedNodes,
"Number of post-indexed nodes created");
91STATISTIC(OpsNarrowed ,
"Number of load/op/store narrowed");
92STATISTIC(LdStFP2Int ,
"Number of fp load/store pairs transformed to int");
94STATISTIC(NumFPLogicOpsConv,
"Number of logic ops converted to fp ops");
97 "Controls whether a DAG combine is performed for a node");
101 cl::desc(
"Enable DAG combiner's use of IR alias analysis"));
105 cl::desc(
"Enable DAG combiner's use of TBAA"));
110 cl::desc(
"Only use DAG-combiner alias analysis in this"
118 cl::desc(
"Bypass the profitability model of load slicing"),
123 cl::desc(
"DAG combiner may split indexing from loads"));
127 cl::desc(
"DAG combiner enable merging multiple stores "
128 "into a wider store"));
132 cl::desc(
"Limit the number of operands to inline for Token Factors"));
136 cl::desc(
"Limit the number of times for the same StoreNode and RootNode "
137 "to bail out in store merging dependence check"));
141 cl::desc(
"DAG combiner enable reducing the width of load/op/store "
144 "combiner-reduce-load-op-store-width-force-narrowing-profitable",
146 cl::desc(
"DAG combiner force override the narrowing profitable check when "
147 "reducing the width of load/op/store sequences"));
151 cl::desc(
"DAG combiner enable load/<replace bytes>/store with "
152 "a narrower store"));
156 cl::desc(
"Disable the DAG combiner"));
166 bool LegalDAG =
false;
167 bool LegalOperations =
false;
168 bool LegalTypes =
false;
170 bool DisableGenericCombines;
206 void AddUsersToWorklist(
SDNode *
N) {
212 void AddToWorklistWithUsers(SDNode *
N) {
213 AddUsersToWorklist(
N);
220 void clearAddedDanglingWorklistEntries() {
222 while (!PruningList.empty()) {
223 auto *
N = PruningList.pop_back_val();
225 recursivelyDeleteUnusedNodes(
N);
229 SDNode *getNextWorklistEntry() {
231 clearAddedDanglingWorklistEntries();
235 while (!
N && !Worklist.empty()) {
236 N = Worklist.pop_back_val();
240 assert(
N->getCombinerWorklistIndex() >= 0 &&
241 "Found a worklist entry without a corresponding map entry!");
243 N->setCombinerWorklistIndex(-2);
253 : DAG(
D), TLI(
D.getTargetLoweringInfo()),
254 STI(
D.getSubtarget().getSelectionDAGInfo()), OptLevel(OL),
256 ForCodeSize = DAG.shouldOptForSize();
257 DisableGenericCombines =
260 MaximumLegalStoreInBits = 0;
264 if (EVT(VT).
isSimple() && VT != MVT::Other &&
265 TLI.isTypeLegal(EVT(VT)) &&
266 VT.getSizeInBits().getKnownMinValue() >= MaximumLegalStoreInBits)
267 MaximumLegalStoreInBits = VT.getSizeInBits().getKnownMinValue();
270 void ConsiderForPruning(SDNode *
N) {
272 PruningList.insert(
N);
277 void AddToWorklist(SDNode *
N,
bool IsCandidateForPruning =
true,
278 bool SkipIfCombinedBefore =
false) {
280 "Deleted Node added to Worklist");
287 if (SkipIfCombinedBefore &&
N->getCombinerWorklistIndex() == -2)
290 if (IsCandidateForPruning)
291 ConsiderForPruning(
N);
293 if (
N->getCombinerWorklistIndex() < 0) {
294 N->setCombinerWorklistIndex(Worklist.size());
295 Worklist.push_back(
N);
300 void removeFromWorklist(SDNode *
N) {
301 PruningList.remove(
N);
302 StoreRootCountMap.erase(
N);
304 int WorklistIndex =
N->getCombinerWorklistIndex();
308 if (WorklistIndex < 0)
312 Worklist[WorklistIndex] =
nullptr;
313 N->setCombinerWorklistIndex(-1);
316 void deleteAndRecombine(SDNode *
N);
317 bool recursivelyDeleteUnusedNodes(SDNode *
N);
325 return CombineTo(
N, &Res, 1, AddTo);
332 return CombineTo(
N, To, 2, AddTo);
335 SDValue CombineTo(SDNode *
N, SmallVectorImpl<SDValue> *To,
337 return CombineTo(
N, To->
data(), To->
size(), AddTo);
340 void CommitTargetLoweringOpt(
const TargetLowering::TargetLoweringOpt &TLO);
343 unsigned MaximumLegalStoreInBits;
349 unsigned BitWidth =
Op.getScalarValueSizeInBits();
351 return SimplifyDemandedBits(
Op, DemandedBits);
354 bool SimplifyDemandedBits(
SDValue Op,
const APInt &DemandedBits) {
355 EVT VT =
Op.getValueType();
359 return SimplifyDemandedBits(
Op, DemandedBits, DemandedElts,
false);
365 bool SimplifyDemandedVectorElts(
SDValue Op) {
367 if (
Op.getValueType().isScalableVector())
370 unsigned NumElts =
Op.getValueType().getVectorNumElements();
372 return SimplifyDemandedVectorElts(
Op, DemandedElts);
375 bool SimplifyDemandedBits(
SDValue Op,
const APInt &DemandedBits,
376 const APInt &DemandedElts,
377 bool AssumeSingleUse =
false);
378 bool SimplifyDemandedVectorElts(
SDValue Op,
const APInt &DemandedElts,
379 bool AssumeSingleUse =
false);
381 bool CombineToPreIndexedLoadStore(SDNode *
N);
382 bool CombineToPostIndexedLoadStore(SDNode *
N);
383 SDValue SplitIndexingFromLoad(LoadSDNode *LD);
384 bool SliceUpLoad(SDNode *
N);
390 StoreSDNode *getUniqueStoreFeeding(LoadSDNode *LD, int64_t &
Offset);
392 SDValue ForwardStoreValueToDirectLoad(LoadSDNode *LD);
393 bool getTruncatedStoreValue(StoreSDNode *ST,
SDValue &Val);
394 bool extendLoadedValueToExtension(LoadSDNode *LD,
SDValue &Val);
396 void ReplaceLoadWithPromotedLoad(SDNode *Load, SDNode *ExtLoad);
405 SDValue foldShiftToAvg(SDNode *
N,
const SDLoc &
DL);
407 SDValue foldBitwiseOpWithNeg(SDNode *
N,
const SDLoc &
DL, EVT VT);
425 SDValue visitTokenFactor(SDNode *
N);
426 SDValue visitMERGE_VALUES(SDNode *
N);
430 SDNode *LocReference);
441 SDValue visitUADDO_CARRY(SDNode *
N);
442 SDValue visitSADDO_CARRY(SDNode *
N);
448 SDValue visitUSUBO_CARRY(SDNode *
N);
449 SDValue visitSSUBO_CARRY(SDNode *
N);
450 template <
class MatchContextClass>
SDValue visitMUL(SDNode *
N);
471 SDValue SimplifyVCastOp(SDNode *
N,
const SDLoc &
DL);
472 SDValue SimplifyVBinOp(SDNode *
N,
const SDLoc &
DL);
476 SDValue visitFunnelShift(SDNode *
N);
483 SDValue visitCTLZ_ZERO_UNDEF(SDNode *
N);
485 SDValue visitCTTZ_ZERO_UNDEF(SDNode *
N);
493 SDValue visitSIGN_EXTEND(SDNode *
N);
494 SDValue visitZERO_EXTEND(SDNode *
N);
497 SDValue visitAssertAlign(SDNode *
N);
498 SDValue visitSIGN_EXTEND_INREG(SDNode *
N);
499 SDValue visitEXTEND_VECTOR_INREG(SDNode *
N);
501 SDValue visitTRUNCATE_USAT_U(SDNode *
N);
508 SDValue visitSTRICT_FADD(SDNode *
N);
511 template <
class MatchContextClass>
SDValue visitFMA(SDNode *
N);
519 SDValue visitFCANONICALIZE(SDNode *
N);
539 SDValue replaceStoreOfFPConstant(StoreSDNode *ST);
540 SDValue replaceStoreOfInsertLoad(StoreSDNode *ST);
542 bool refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(SDNode *
N);
545 SDValue visitATOMIC_STORE(SDNode *
N);
546 SDValue visitLIFETIME_END(SDNode *
N);
547 SDValue visitINSERT_VECTOR_ELT(SDNode *
N);
548 SDValue visitEXTRACT_VECTOR_ELT(SDNode *
N);
549 SDValue visitBUILD_VECTOR(SDNode *
N);
550 SDValue visitCONCAT_VECTORS(SDNode *
N);
551 SDValue visitVECTOR_INTERLEAVE(SDNode *
N);
552 SDValue visitEXTRACT_SUBVECTOR(SDNode *
N);
553 SDValue visitVECTOR_SHUFFLE(SDNode *
N);
554 SDValue visitSCALAR_TO_VECTOR(SDNode *
N);
555 SDValue visitINSERT_SUBVECTOR(SDNode *
N);
556 SDValue visitVECTOR_COMPRESS(SDNode *
N);
562 SDValue visitPARTIAL_REDUCE_MLA(SDNode *
N);
565 SDValue visitVP_STRIDED_LOAD(SDNode *
N);
566 SDValue visitVP_STRIDED_STORE(SDNode *
N);
573 SDValue visitGET_FPENV_MEM(SDNode *
N);
574 SDValue visitSET_FPENV_MEM(SDNode *
N);
576 template <
class MatchContextClass>
577 SDValue visitFADDForFMACombine(SDNode *
N);
578 template <
class MatchContextClass>
579 SDValue visitFSUBForFMACombine(SDNode *
N);
580 SDValue visitFMULForFMADistributiveCombine(SDNode *
N);
582 SDValue XformToShuffleWithZero(SDNode *
N);
583 bool reassociationCanBreakAddressingModePattern(
unsigned Opc,
589 SDValue N1, SDNodeFlags Flags);
591 SDValue N1, SDNodeFlags Flags);
592 SDValue reassociateReduction(
unsigned RedOpc,
unsigned Opc,
const SDLoc &
DL,
594 SDNodeFlags Flags = SDNodeFlags());
596 SDValue visitShiftByConstant(SDNode *
N);
598 SDValue foldSelectOfConstants(SDNode *
N);
599 SDValue foldVSelectOfConstants(SDNode *
N);
600 SDValue foldBinOpIntoSelect(SDNode *BO);
602 SDValue hoistLogicOpWithSameOpcodeHands(SDNode *
N);
606 bool NotExtCompare =
false);
607 SDValue convertSelectOfFPConstantsToLoadOffset(
610 SDValue foldSignChangeInBitcast(SDNode *
N);
613 SDValue foldSelectOfBinops(SDNode *
N);
617 SDValue foldSubToUSubSat(EVT DstVT, SDNode *
N,
const SDLoc &
DL);
618 SDValue foldABSToABD(SDNode *
N,
const SDLoc &
DL);
623 SDValue unfoldMaskedMerge(SDNode *
N);
624 SDValue unfoldExtremeBitClearingToShifts(SDNode *
N);
626 const SDLoc &
DL,
bool foldBooleans);
630 SDValue &CC,
bool MatchStrict =
false)
const;
631 bool isOneUseSetCC(
SDValue N)
const;
633 SDValue foldAddToAvg(SDNode *
N,
const SDLoc &
DL);
634 SDValue foldSubToAvg(SDNode *
N,
const SDLoc &
DL);
636 SDValue SimplifyNodeWithTwoResults(SDNode *
N,
unsigned LoOp,
638 SDValue CombineConsecutiveLoads(SDNode *
N, EVT VT);
639 SDValue foldBitcastedFPLogic(SDNode *
N, SelectionDAG &DAG,
640 const TargetLowering &TLI);
641 SDValue foldPartialReduceMLAMulOp(SDNode *
N);
642 SDValue foldPartialReduceAdd(SDNode *
N);
645 SDValue CombineZExtLogicopShiftLoad(SDNode *
N);
646 SDValue combineRepeatedFPDivisors(SDNode *
N);
647 SDValue combineFMulOrFDivWithIntPow2(SDNode *
N);
648 SDValue replaceShuffleOfInsert(ShuffleVectorSDNode *Shuf);
649 SDValue mergeInsertEltWithShuffle(SDNode *
N,
unsigned InsIndex);
650 SDValue combineInsertEltToShuffle(SDNode *
N,
unsigned InsIndex);
651 SDValue combineInsertEltToLoad(SDNode *
N,
unsigned InsIndex);
658 bool KnownNeverZero =
false,
659 bool InexpensiveOnly =
false,
660 std::optional<EVT> OutVT = std::nullopt);
670 bool DemandHighBits =
true);
674 bool HasPos,
unsigned PosOpcode,
675 unsigned NegOpcode,
const SDLoc &
DL);
678 bool HasPos,
unsigned PosOpcode,
679 unsigned NegOpcode,
const SDLoc &
DL);
682 SDValue MatchLoadCombine(SDNode *
N);
683 SDValue mergeTruncStores(StoreSDNode *
N);
685 SDValue ReduceLoadOpStoreWidth(SDNode *
N);
687 SDValue TransformFPLoadStorePair(SDNode *
N);
688 SDValue convertBuildVecZextToZext(SDNode *
N);
689 SDValue convertBuildVecZextToBuildVecWithZeros(SDNode *
N);
690 SDValue reduceBuildVecExtToExtBuildVec(SDNode *
N);
691 SDValue reduceBuildVecTruncToBitCast(SDNode *
N);
692 SDValue reduceBuildVecToShuffle(SDNode *
N);
693 SDValue createBuildVecShuffle(
const SDLoc &
DL, SDNode *
N,
694 ArrayRef<int> VectorMask,
SDValue VecIn1,
695 SDValue VecIn2,
unsigned LeftIdx,
697 SDValue matchVSelectOpSizesWithSetCC(SDNode *Cast);
701 void GatherAllAliases(SDNode *
N,
SDValue OriginalChain,
702 SmallVectorImpl<SDValue> &Aliases);
705 bool mayAlias(SDNode *Op0, SDNode *Op1)
const;
717 bool findBetterNeighborChains(StoreSDNode *St);
721 bool parallelizeChainedStores(StoreSDNode *St);
727 LSBaseSDNode *MemNode;
730 int64_t OffsetFromBase;
732 MemOpLink(LSBaseSDNode *
N, int64_t
Offset)
733 : MemNode(
N), OffsetFromBase(
Offset) {}
738 StoreSource getStoreSource(
SDValue StoreVal) {
742 return StoreSource::Constant;
746 return StoreSource::Constant;
747 return StoreSource::Unknown;
750 return StoreSource::Extract;
752 return StoreSource::Load;
754 return StoreSource::Unknown;
762 bool isMulAddWithConstProfitable(SDNode *MulNode,
SDValue AddNode,
768 bool isAndLoadExtLoad(ConstantSDNode *AndC, LoadSDNode *LoadN,
769 EVT LoadResultTy, EVT &ExtVT);
774 EVT &MemVT,
unsigned ShAmt = 0);
777 bool SearchForAndLoads(SDNode *
N, SmallVectorImpl<LoadSDNode*> &Loads,
778 SmallPtrSetImpl<SDNode*> &NodesWithConsts,
779 ConstantSDNode *Mask, SDNode *&NodeToMask);
782 bool BackwardsPropagateMask(SDNode *
N);
786 SDValue getMergeStoreChains(SmallVectorImpl<MemOpLink> &StoreNodes,
798 bool mergeStoresOfConstantsOrVecElts(SmallVectorImpl<MemOpLink> &StoreNodes,
799 EVT MemVT,
unsigned NumStores,
800 bool IsConstantSrc,
bool UseVector,
806 SDNode *getStoreMergeCandidates(StoreSDNode *St,
807 SmallVectorImpl<MemOpLink> &StoreNodes);
813 bool checkMergeStoreCandidatesForDependencies(
814 SmallVectorImpl<MemOpLink> &StoreNodes,
unsigned NumStores,
819 bool hasCallInLdStChain(StoreSDNode *St, LoadSDNode *Ld);
824 unsigned getConsecutiveStores(SmallVectorImpl<MemOpLink> &StoreNodes,
825 int64_t ElementSizeBytes)
const;
829 bool tryStoreMergeOfConstants(SmallVectorImpl<MemOpLink> &StoreNodes,
830 unsigned NumConsecutiveStores,
831 EVT MemVT, SDNode *Root,
bool AllowVectors);
837 bool tryStoreMergeOfExtracts(SmallVectorImpl<MemOpLink> &StoreNodes,
838 unsigned NumConsecutiveStores, EVT MemVT,
843 bool tryStoreMergeOfLoads(SmallVectorImpl<MemOpLink> &StoreNodes,
844 unsigned NumConsecutiveStores, EVT MemVT,
845 SDNode *Root,
bool AllowVectors,
846 bool IsNonTemporalStore,
bool IsNonTemporalLoad);
851 bool mergeConsecutiveStores(StoreSDNode *St);
859 SDValue distributeTruncateThroughAnd(SDNode *
N);
865 bool hasOperation(
unsigned Opcode, EVT VT) {
866 return TLI.isOperationLegalOrCustom(Opcode, VT, LegalOperations);
869 bool hasUMin(EVT VT)
const {
870 auto LK = TLI.getTypeConversion(*DAG.getContext(), VT);
873 TLI.isOperationLegalOrCustom(
ISD::UMIN, LK.second);
880 SelectionDAG &getDAG()
const {
return DAG; }
883 EVT getShiftAmountTy(EVT LHSTy) {
884 return TLI.getShiftAmountTy(LHSTy, DAG.getDataLayout());
889 bool isTypeLegal(
const EVT &VT) {
890 if (!LegalTypes)
return true;
891 return TLI.isTypeLegal(VT);
895 EVT getSetCCResultType(EVT VT)
const {
896 return TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
899 void ExtendSetCCUses(
const SmallVectorImpl<SDNode *> &SetCCs,
910 explicit WorklistRemover(DAGCombiner &dc)
911 : SelectionDAG::DAGUpdateListener(dc.getDAG()), DC(dc) {}
913 void NodeDeleted(SDNode *
N, SDNode *
E)
override {
914 DC.removeFromWorklist(
N);
922 explicit WorklistInserter(DAGCombiner &dc)
923 : SelectionDAG::DAGUpdateListener(dc.getDAG()), DC(dc) {}
927 void NodeInserted(SDNode *
N)
override { DC.ConsiderForPruning(
N); }
937 ((DAGCombiner*)
DC)->AddToWorklist(
N);
942 return ((DAGCombiner*)
DC)->CombineTo(
N, &To[0], To.
size(), AddTo);
947 return ((DAGCombiner*)
DC)->CombineTo(
N, Res, AddTo);
952 return ((DAGCombiner*)
DC)->CombineTo(
N, Res0, Res1, AddTo);
957 return ((DAGCombiner*)
DC)->recursivelyDeleteUnusedNodes(
N);
962 return ((DAGCombiner*)
DC)->CommitTargetLoweringOpt(TLO);
969void DAGCombiner::deleteAndRecombine(
SDNode *
N) {
970 removeFromWorklist(
N);
978 if (
Op->hasOneUse() ||
Op->getNumValues() > 1)
979 AddToWorklist(
Op.getNode());
988 unsigned Bits =
Offset + std::max(
LHS.getBitWidth(),
RHS.getBitWidth());
999 SDValue &CC,
bool MatchStrict)
const {
1001 LHS =
N.getOperand(0);
1002 RHS =
N.getOperand(1);
1010 LHS =
N.getOperand(1);
1011 RHS =
N.getOperand(2);
1024 LHS =
N.getOperand(0);
1025 RHS =
N.getOperand(1);
1033bool DAGCombiner::isOneUseSetCC(
SDValue N)
const {
1035 if (isSetCCEquivalent(
N, N0, N1, N2) &&
N->hasOneUse())
1047 MaskForTy = 0xFFULL;
1050 MaskForTy = 0xFFFFULL;
1053 MaskForTy = 0xFFFFFFFFULL;
1071 bool AllowTruncation =
false) {
1073 return !(Const->isOpaque() && NoOpaques);
1076 unsigned BitWidth =
N.getScalarValueSizeInBits();
1081 if (!Const || (Const->isOpaque() && NoOpaques))
1085 if ((AllowTruncation &&
1086 Const->getAPIntValue().getActiveBits() >
BitWidth) ||
1087 (!AllowTruncation && Const->getAPIntValue().getBitWidth() !=
BitWidth))
1109bool DAGCombiner::reassociationCanBreakAddressingModePattern(
unsigned Opc,
1137 : (N1.
getOperand(0).getConstantOperandVal(0) *
1142 ScalableOffset = -ScalableOffset;
1143 if (
all_of(
N->users(), [&](SDNode *Node) {
1144 if (auto *LoadStore = dyn_cast<MemSDNode>(Node);
1145 LoadStore && LoadStore->getBasePtr().getNode() == N) {
1146 TargetLoweringBase::AddrMode AM;
1147 AM.HasBaseReg = true;
1148 AM.ScalableOffset = ScalableOffset;
1149 EVT VT = LoadStore->getMemoryVT();
1150 unsigned AS = LoadStore->getAddressSpace();
1151 Type *AccessTy = VT.getTypeForEVT(*DAG.getContext());
1152 return TLI.isLegalAddressingMode(DAG.getDataLayout(), AM, AccessTy,
1167 const APInt &C2APIntVal = C2->getAPIntValue();
1175 const APInt &C1APIntVal = C1->getAPIntValue();
1176 const APInt CombinedValueIntVal = C1APIntVal + C2APIntVal;
1179 const int64_t CombinedValue = CombinedValueIntVal.
getSExtValue();
1181 for (SDNode *Node :
N->users()) {
1186 TargetLoweringBase::AddrMode AM;
1188 AM.
BaseOffs = C2APIntVal.getSExtValue();
1190 unsigned AS =
LoadStore->getAddressSpace();
1206 for (SDNode *Node :
N->users()) {
1213 TargetLoweringBase::AddrMode AM;
1215 AM.
BaseOffs = C2APIntVal.getSExtValue();
1217 unsigned AS =
LoadStore->getAddressSpace();
1230SDValue DAGCombiner::reassociateOpsCommutative(
unsigned Opc,
const SDLoc &
DL,
1232 SDNodeFlags Flags) {
1242 SDNodeFlags NewFlags;
1244 Flags.hasNoUnsignedWrap())
1252 return DAG.
getNode(
Opc,
DL, VT, N00, OpNode, NewFlags);
1260 return DAG.
getNode(
Opc,
DL, VT, OpNode, N01, NewFlags);
1270 if (N1 == N00 || N1 == N01)
1316 if (CC1 == CC00 && CC1 != CC01) {
1320 if (CC1 == CC01 && CC1 != CC00) {
1334 SDValue N1, SDNodeFlags Flags) {
1340 if (!
Flags.hasAllowReassociation() || !
Flags.hasNoSignedZeros())
1343 if (
SDValue Combined = reassociateOpsCommutative(
Opc,
DL, N0, N1, Flags))
1345 if (
SDValue Combined = reassociateOpsCommutative(
Opc,
DL, N1, N0, Flags))
1353SDValue DAGCombiner::reassociateReduction(
unsigned RedOpc,
unsigned Opc,
1355 SDValue N1, SDNodeFlags Flags) {
1361 SelectionDAG::FlagInserter FlagsInserter(DAG, Flags);
1383 A.getValueType() ==
C.getValueType() &&
1384 hasOperation(
Opc,
A.getValueType()) &&
1392 SelectionDAG::FlagInserter FlagsInserter(
1403SDValue DAGCombiner::CombineTo(SDNode *
N,
const SDValue *To,
unsigned NumTo,
1405 assert(
N->getNumValues() == NumTo &&
"Broken CombineTo call!");
1409 dbgs() <<
" and " << NumTo - 1 <<
" other values\n");
1410 for (
unsigned i = 0, e = NumTo; i !=
e; ++i)
1412 N->getValueType(i) == To[i].getValueType()) &&
1413 "Cannot combine value to value of different type!");
1415 WorklistRemover DeadNodes(*
this);
1419 for (
unsigned i = 0, e = NumTo; i !=
e; ++i) {
1421 AddToWorklistWithUsers(To[i].
getNode());
1429 deleteAndRecombine(
N);
1434CommitTargetLoweringOpt(
const TargetLowering::TargetLoweringOpt &TLO) {
1447 recursivelyDeleteUnusedNodes(TLO.
Old.
getNode());
1452bool DAGCombiner::SimplifyDemandedBits(
SDValue Op,
const APInt &DemandedBits,
1453 const APInt &DemandedElts,
1454 bool AssumeSingleUse) {
1455 TargetLowering::TargetLoweringOpt TLO(DAG, LegalTypes, LegalOperations);
1462 AddToWorklist(
Op.getNode());
1464 CommitTargetLoweringOpt(TLO);
1471bool DAGCombiner::SimplifyDemandedVectorElts(
SDValue Op,
1472 const APInt &DemandedElts,
1473 bool AssumeSingleUse) {
1474 TargetLowering::TargetLoweringOpt TLO(DAG, LegalTypes, LegalOperations);
1475 APInt KnownUndef, KnownZero;
1477 TLO, 0, AssumeSingleUse))
1481 AddToWorklist(
Op.getNode());
1483 CommitTargetLoweringOpt(TLO);
1487void DAGCombiner::ReplaceLoadWithPromotedLoad(SDNode *Load, SDNode *ExtLoad) {
1489 EVT VT =
Load->getValueType(0);
1498 AddToWorklist(Trunc.
getNode());
1499 recursivelyDeleteUnusedNodes(Load);
1507 EVT MemVT =
LD->getMemoryVT();
1509 :
LD->getExtensionType();
1512 LD->getChain(),
LD->getBasePtr(),
1513 MemVT,
LD->getMemOperand());
1516 unsigned Opc =
Op.getOpcode();
1520 if (
SDValue Op0 = SExtPromoteOperand(
Op.getOperand(0), PVT))
1524 if (
SDValue Op0 = ZExtPromoteOperand(
Op.getOperand(0), PVT))
1542 EVT OldVT =
Op.getValueType();
1544 bool Replace =
false;
1545 SDValue NewOp = PromoteOperand(
Op, PVT, Replace);
1548 AddToWorklist(NewOp.
getNode());
1551 ReplaceLoadWithPromotedLoad(
Op.getNode(), NewOp.
getNode());
1557 EVT OldVT =
Op.getValueType();
1559 bool Replace =
false;
1560 SDValue NewOp = PromoteOperand(
Op, PVT, Replace);
1563 AddToWorklist(NewOp.
getNode());
1566 ReplaceLoadWithPromotedLoad(
Op.getNode(), NewOp.
getNode());
1574 if (!LegalOperations)
1577 EVT VT =
Op.getValueType();
1583 unsigned Opc =
Op.getOpcode();
1591 assert(PVT != VT &&
"Don't know what type to promote to!");
1595 bool Replace0 =
false;
1597 SDValue NN0 = PromoteOperand(N0, PVT, Replace0);
1599 bool Replace1 =
false;
1601 SDValue NN1 = PromoteOperand(N1, PVT, Replace1);
1613 Replace1 &= (N0 != N1) && !N1->
hasOneUse();
1616 CombineTo(
Op.getNode(), RV);
1642 if (!LegalOperations)
1645 EVT VT =
Op.getValueType();
1651 unsigned Opc =
Op.getOpcode();
1659 assert(PVT != VT &&
"Don't know what type to promote to!");
1663 bool Replace =
false;
1666 N0 = SExtPromoteOperand(N0, PVT);
1668 N0 = ZExtPromoteOperand(N0, PVT);
1670 N0 = PromoteOperand(N0, PVT, Replace);
1681 ReplaceLoadWithPromotedLoad(
Op.getOperand(0).getNode(), N0.
getNode());
1691 if (!LegalOperations)
1694 EVT VT =
Op.getValueType();
1700 unsigned Opc =
Op.getOpcode();
1708 assert(PVT != VT &&
"Don't know what type to promote to!");
1713 return DAG.
getNode(
Op.getOpcode(), SDLoc(
Op), VT,
Op.getOperand(0));
1718bool DAGCombiner::PromoteLoad(
SDValue Op) {
1719 if (!LegalOperations)
1725 EVT VT =
Op.getValueType();
1731 unsigned Opc =
Op.getOpcode();
1739 assert(PVT != VT &&
"Don't know what type to promote to!");
1742 SDNode *
N =
Op.getNode();
1744 EVT MemVT =
LD->getMemoryVT();
1746 :
LD->getExtensionType();
1748 LD->getChain(),
LD->getBasePtr(),
1749 MemVT,
LD->getMemOperand());
1758 AddToWorklist(
Result.getNode());
1759 recursivelyDeleteUnusedNodes(
N);
1772bool DAGCombiner::recursivelyDeleteUnusedNodes(SDNode *
N) {
1773 if (!
N->use_empty())
1776 SmallSetVector<SDNode *, 16> Nodes;
1783 if (
N->use_empty()) {
1784 for (
const SDValue &ChildN :
N->op_values())
1785 Nodes.
insert(ChildN.getNode());
1787 removeFromWorklist(
N);
1792 }
while (!Nodes.
empty());
1807 WorklistInserter AddNodes(*
this);
1815 for (SDNode &Node : DAG.
allnodes())
1816 AddToWorklist(&Node,
Node.use_empty());
1821 HandleSDNode Dummy(DAG.
getRoot());
1824 while (SDNode *
N = getNextWorklistEntry()) {
1828 if (recursivelyDeleteUnusedNodes(
N))
1831 WorklistRemover DeadNodes(*
this);
1836 SmallSetVector<SDNode *, 16> UpdatedNodes;
1839 for (SDNode *LN : UpdatedNodes)
1840 AddToWorklistWithUsers(LN);
1852 for (
const SDValue &ChildN :
N->op_values())
1853 AddToWorklist(ChildN.getNode(),
true,
1864 ChainsWithoutMergeableStores.
clear();
1875 "Node was deleted but visit returned new node!");
1883 N->getNumValues() == 1 &&
"Type mismatch");
1893 AddToWorklistWithUsers(RV.
getNode());
1899 recursivelyDeleteUnusedNodes(
N);
1903 DAG.
setRoot(Dummy.getValue());
1907SDValue DAGCombiner::visit(SDNode *
N) {
1909 switch (
N->getOpcode()) {
1936 case ISD::MUL:
return visitMUL<EmptyMatchContext>(
N);
2000 case ISD::FMA:
return visitFMA<EmptyMatchContext>(
N);
2053 return visitPARTIAL_REDUCE_MLA(
N);
2079#define BEGIN_REGISTER_VP_SDNODE(SDOPC, ...) case ISD::SDOPC:
2080#include "llvm/IR/VPIntrinsics.def"
2081 return visitVPOp(
N);
2087SDValue DAGCombiner::combine(SDNode *
N) {
2092 if (!DisableGenericCombines)
2098 "Node was deleted but visit returned NULL!");
2104 TargetLowering::DAGCombinerInfo
2105 DagCombineInfo(DAG, Level,
false,
this);
2113 switch (
N->getOpcode()) {
2121 RV = PromoteIntBinOp(
SDValue(
N, 0));
2126 RV = PromoteIntShiftOp(
SDValue(
N, 0));
2162 if (
unsigned NumOps =
N->getNumOperands()) {
2163 if (
N->getOperand(0).getValueType() == MVT::Other)
2164 return N->getOperand(0);
2165 if (
N->getOperand(
NumOps-1).getValueType() == MVT::Other)
2166 return N->getOperand(
NumOps-1);
2167 for (
unsigned i = 1; i <
NumOps-1; ++i)
2168 if (
N->getOperand(i).getValueType() == MVT::Other)
2169 return N->getOperand(i);
2174SDValue DAGCombiner::visitFCANONICALIZE(SDNode *
N) {
2175 SDValue Operand =
N->getOperand(0);
2187SDValue DAGCombiner::visitTokenFactor(SDNode *
N) {
2190 if (
N->getNumOperands() == 2) {
2192 return N->getOperand(0);
2194 return N->getOperand(1);
2209 AddToWorklist(*(
N->user_begin()));
2213 SmallPtrSet<SDNode*, 16> SeenOps;
2221 for (
unsigned i = 0; i < TFs.
size(); ++i) {
2226 for (
unsigned j = i;
j < TFs.
size();
j++)
2227 Ops.emplace_back(TFs[j], 0);
2234 SDNode *TF = TFs[i];
2237 switch (
Op.getOpcode()) {
2255 if (SeenOps.
insert(
Op.getNode()).second)
2266 for (
unsigned i = 1, e = TFs.
size(); i < e; i++)
2267 AddToWorklist(TFs[i]);
2277 SmallVector<unsigned, 8> OpWorkCount;
2278 SmallPtrSet<SDNode *, 16> SeenChains;
2279 bool DidPruneOps =
false;
2281 unsigned NumLeftToConsider = 0;
2283 Worklist.
push_back(std::make_pair(
Op.getNode(), NumLeftToConsider++));
2287 auto AddToWorklist = [&](
unsigned CurIdx, SDNode *
Op,
unsigned OpNumber) {
2293 unsigned OrigOpNumber = 0;
2294 while (OrigOpNumber <
Ops.size() &&
Ops[OrigOpNumber].getNode() !=
Op)
2297 "expected to find TokenFactor Operand");
2299 for (
unsigned i = CurIdx + 1; i < Worklist.
size(); ++i) {
2300 if (Worklist[i].second == OrigOpNumber) {
2301 Worklist[i].second = OpNumber;
2304 OpWorkCount[OpNumber] += OpWorkCount[OrigOpNumber];
2305 OpWorkCount[OrigOpNumber] = 0;
2306 NumLeftToConsider--;
2309 if (SeenChains.
insert(
Op).second) {
2310 OpWorkCount[OpNumber]++;
2315 for (
unsigned i = 0; i < Worklist.
size() && i < 1024; ++i) {
2317 if (NumLeftToConsider <= 1)
2319 auto CurNode = Worklist[i].first;
2320 auto CurOpNumber = Worklist[i].second;
2321 assert((OpWorkCount[CurOpNumber] > 0) &&
2322 "Node should not appear in worklist");
2323 switch (CurNode->getOpcode()) {
2329 NumLeftToConsider++;
2332 for (
const SDValue &
Op : CurNode->op_values())
2333 AddToWorklist(i,
Op.getNode(), CurOpNumber);
2339 AddToWorklist(i, CurNode->getOperand(0).getNode(), CurOpNumber);
2343 AddToWorklist(i, MemNode->getChain().getNode(), CurOpNumber);
2346 OpWorkCount[CurOpNumber]--;
2347 if (OpWorkCount[CurOpNumber] == 0)
2348 NumLeftToConsider--;
2362 if (SeenChains.
count(
Op.getNode()) == 0)
2376SDValue DAGCombiner::visitMERGE_VALUES(SDNode *
N) {
2377 WorklistRemover DeadNodes(*
this);
2383 AddUsersToWorklist(
N);
2388 }
while (!
N->use_empty());
2389 deleteAndRecombine(
N);
2397 return Const !=
nullptr && !Const->isOpaque() ? Const :
nullptr;
2407 Op =
N->getOperand(0);
2409 if (
N->getFlags().hasNoUnsignedWrap())
2414 if (
N.getValueType().getScalarType() != MVT::i1 ||
2431 if (LD->isIndexed() || LD->getBasePtr().getNode() !=
N)
2433 VT = LD->getMemoryVT();
2434 AS = LD->getAddressSpace();
2436 if (ST->isIndexed() || ST->getBasePtr().getNode() !=
N)
2438 VT = ST->getMemoryVT();
2439 AS = ST->getAddressSpace();
2441 if (LD->isIndexed() || LD->getBasePtr().getNode() !=
N)
2443 VT = LD->getMemoryVT();
2444 AS = LD->getAddressSpace();
2446 if (ST->isIndexed() || ST->getBasePtr().getNode() !=
N)
2448 VT = ST->getMemoryVT();
2449 AS = ST->getAddressSpace();
2455 if (
N->isAnyAdd()) {
2464 }
else if (
N->getOpcode() ==
ISD::SUB) {
2486 bool ShouldCommuteOperands) {
2492 if (ShouldCommuteOperands)
2506 unsigned Opcode =
N->getOpcode();
2507 EVT VT =
N->getValueType(0);
2512 unsigned OpNo = ShouldCommuteOperands ? 0 : 1;
2532SDValue DAGCombiner::foldBinOpIntoSelect(SDNode *BO) {
2535 "Unexpected binary operator");
2547 unsigned SelOpNo = 0;
2584 bool CanFoldNonConst =
2590 if (!CanFoldNonConst &&
2599 if (CanFoldNonConst) {
2618 : DAG.FoldConstantArithmetic(BinOpcode,
DL, VT, {CT, CBO});
2623 : DAG.FoldConstantArithmetic(BinOpcode,
DL, VT, {CF, CBO});
2634 "Expecting add or sub");
2639 bool IsAdd =
N->getOpcode() ==
ISD::ADD;
2640 SDValue C = IsAdd ?
N->getOperand(1) :
N->getOperand(0);
2641 SDValue Z = IsAdd ?
N->getOperand(0) :
N->getOperand(1);
2647 if (Z.getOperand(0).getValueType() != MVT::i1)
2659 EVT VT =
C.getValueType();
2667SDValue DAGCombiner::foldSubToAvg(SDNode *
N,
const SDLoc &
DL) {
2672 if ((!LegalOperations || hasOperation(
ISD::AVGCEILU, VT)) &&
2677 if ((!LegalOperations || hasOperation(
ISD::AVGCEILS, VT)) &&
2688SDValue DAGCombiner::visitPTRADD(SDNode *
N) {
2698 "PTRADD with different operand types is not supported");
2709 !reassociationCanBreakAddressingModePattern(
ISD::PTRADD,
DL,
N, N0, N1)) {
2720 if ((YIsConstant && N0OneUse) || (YIsConstant && ZIsConstant)) {
2725 AddToWorklist(
Add.getNode());
2749 if (
const GlobalAddressSDNode *GA =
2764 AddToWorklist(Inner.
getNode());
2786 SDNodeFlags CommonFlags =
N->getFlags() & N1->
getFlags();
2794 if (ZIsConstant != YIsConstant) {
2798 AddToWorklist(Inner.
getNode());
2808 bool TransformCannotBreakAddrMode =
none_of(
N->users(), [&](SDNode *User) {
2809 return canFoldInAddressingMode(N, User, DAG, TLI);
2812 if (TransformCannotBreakAddrMode)
2824 "Expecting add or sub");
2828 bool IsAdd =
N->getOpcode() ==
ISD::ADD;
2829 SDValue ConstantOp = IsAdd ?
N->getOperand(1) :
N->getOperand(0);
2830 SDValue ShiftOp = IsAdd ?
N->getOperand(0) :
N->getOperand(1);
2852 {ConstantOp, DAG.getConstant(1, DL, VT)})) {
2854 Not.getOperand(0), ShAmt);
2870SDValue DAGCombiner::visitADDLike(SDNode *
N) {
2896 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
2928 if ((!LegalOperations ||
2931 X.getScalarValueSizeInBits() == 1) {
2947 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
2951 if (!reassociationCanBreakAddressingModePattern(
ISD::ADD,
DL,
N, N0, N1)) {
3038 auto MatchUSUBSAT = [](ConstantSDNode *
Max, ConstantSDNode *
Op) {
3039 return (!Max && !
Op) ||
3040 (
Max &&
Op &&
Max->getAPIntValue() == (-
Op->getAPIntValue()));
3081 !
N->getFlags().hasNoSignedWrap()))) {
3102 (CA * CM + CB->getAPIntValue()).getSExtValue())) {
3106 if (
N->getFlags().hasNoUnsignedWrap() &&
3110 if (
N->getFlags().hasNoSignedWrap() &&
3119 DAG.
getConstant(CA * CM + CB->getAPIntValue(),
DL, VT), Flags);
3127 (CA * CM + CB->getAPIntValue()).getSExtValue())) {
3133 if (
N->getFlags().hasNoUnsignedWrap() &&
3138 if (
N->getFlags().hasNoSignedWrap() &&
3149 DAG.
getConstant(CA * CM + CB->getAPIntValue(),
DL, VT), Flags);
3154 if (
SDValue Combined = visitADDLikeCommutative(N0, N1,
N))
3157 if (
SDValue Combined = visitADDLikeCommutative(N1, N0,
N))
3165SDValue DAGCombiner::foldAddToAvg(SDNode *
N,
const SDLoc &
DL) {
3194SDValue DAGCombiner::visitADD(SDNode *
N) {
3200 if (
SDValue Combined = visitADDLike(
N))
3209 if (
SDValue V = MatchRotate(N0, N1, SDLoc(
N),
true))
3243 APInt NewStep = C0 + C1;
3253 APInt NewStep = SV0 + SV1;
3261SDValue DAGCombiner::visitADDSAT(SDNode *
N) {
3262 unsigned Opcode =
N->getOpcode();
3280 return DAG.
getNode(Opcode,
DL, VT, N1, N0);
3284 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
3304 bool ForceCarryReconstruction =
false) {
3309 if (ForceCarryReconstruction && V.getValueType() == MVT::i1)
3313 V = V.getOperand(0);
3318 if (ForceCarryReconstruction)
3322 V = V.getOperand(0);
3330 if (V.getResNo() != 1)
3337 EVT VT = V->getValueType(0);
3381 SDNode *LocReference) {
3383 SDLoc
DL(LocReference);
3445 if (TN->
getVT() == MVT::i1) {
3462 DAG.
getVTList(VT, Carry.getValueType()), N0,
3468SDValue DAGCombiner::visitADDC(SDNode *
N) {
3475 if (!
N->hasAnyUseOfValue(1))
3515 return V.getOperand(0);
3521SDValue DAGCombiner::visitADDO(SDNode *
N) {
3527 EVT CarryVT =
N->getValueType(1);
3531 if (!
N->hasAnyUseOfValue(1))
3538 return DAG.
getNode(
N->getOpcode(),
DL,
N->getVTList(), N1, N0);
3563 if (
SDValue Combined = visitUADDOLike(N0, N1,
N))
3566 if (
SDValue Combined = visitUADDOLike(N1, N0,
N))
3597SDValue DAGCombiner::visitADDE(SDNode *
N) {
3616SDValue DAGCombiner::visitUADDO_CARRY(SDNode *
N) {
3630 if (!LegalOperations ||
3640 AddToWorklist(CarryExt.
getNode());
3646 if (
SDValue Combined = visitUADDO_CARRYLike(N0, N1, CarryIn,
N))
3649 if (
SDValue Combined = visitUADDO_CARRYLike(N1, N0, CarryIn,
N))
3796 EVT CarryOutType =
N->getValueType(0);
3812 unsigned CarryInOperandNum =
3814 if (Opcode ==
ISD::USUBO && CarryInOperandNum != 1)
3905SDValue DAGCombiner::visitSADDO_CARRY(SDNode *
N) {
3919 if (!LegalOperations ||
3924 if (
SDValue Combined = visitSADDO_CARRYLike(N0, N1, CarryIn,
N))
3927 if (
SDValue Combined = visitSADDO_CARRYLike(N1, N0, CarryIn,
N))
3939 "Illegal truncation");
3963SDValue DAGCombiner::foldSubToUSubSat(EVT DstVT, SDNode *
N,
const SDLoc &
DL) {
3965 !(!LegalOperations || hasOperation(
ISD::USUBSAT, DstVT)))
3968 EVT SubVT =
N->getValueType(0);
4036template <
class MatchContextClass>
4059 if ((
BitWidth - Src.getValueType().getScalarSizeInBits()) != BitWidthDiff)
4071 if (!(AndMask.
isMask(AndMaskWidth) && XorMask.
countr_one() >= AndMaskWidth))
4106 if (
SDValue Res = CheckAndFoldMulCase(Mul0, Mul1))
4109 if (
SDValue Res = CheckAndFoldMulCase(Mul1, Mul0))
4147SDValue DAGCombiner::visitSUB(SDNode *
N) {
4167 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4194 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4217 if (
N->getFlags().hasNoUnsignedWrap())
4223 if (
N->getFlags().hasNoSignedWrap())
4249 if (hasOperation(NewOpc, VT))
4394 if (!reassociationCanBreakAddressingModePattern(
ISD::SUB,
DL,
N, N0, N1) &&
4432 if ((!LegalOperations || hasOperation(
ISD::ABS, VT)) &&
4442 if (GA->getGlobal() == GB->getGlobal())
4443 return DAG.
getConstant((uint64_t)GA->getOffset() - GB->getOffset(),
4450 if (TN->
getVT() == MVT::i1) {
4503 DAG.
getVTList(VT, Carry.getValueType()), NegX, Zero,
4511 if (!C0->isOpaque()) {
4512 const APInt &C0Val = C0->getAPIntValue();
4513 const APInt &MaybeOnes = ~DAG.computeKnownBits(N1).Zero;
4514 if ((C0Val - MaybeOnes) == (C0Val ^ MaybeOnes))
4520 if ((!LegalOperations || hasOperation(
ISD::ABDS, VT)) &&
4532 if ((!LegalOperations || hasOperation(
ISD::ABDU, VT)) &&
4546SDValue DAGCombiner::visitSUBSAT(SDNode *
N) {
4547 unsigned Opcode =
N->getOpcode();
4568 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4587SDValue DAGCombiner::visitSUBC(SDNode *
N) {
4594 if (!
N->hasAnyUseOfValue(1))
4615SDValue DAGCombiner::visitSUBO(SDNode *
N) {
4621 EVT CarryVT =
N->getValueType(1);
4625 if (!
N->hasAnyUseOfValue(1))
4657SDValue DAGCombiner::visitSUBE(SDNode *
N) {
4669SDValue DAGCombiner::visitUSUBO_CARRY(SDNode *
N) {
4676 if (!LegalOperations ||
4684SDValue DAGCombiner::visitSSUBO_CARRY(SDNode *
N) {
4691 if (!LegalOperations ||
4701SDValue DAGCombiner::visitMULFIX(SDNode *
N) {
4714 return DAG.
getNode(
N->getOpcode(), SDLoc(
N), VT, N1, N0, Scale);
4723template <
class MatchContextClass>
SDValue DAGCombiner::visitMUL(SDNode *
N) {
4729 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
4730 MatchContextClass Matcher(DAG, TLI,
N);
4745 bool N1IsConst =
false;
4746 bool N1IsOpaqueConst =
false;
4753 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4758 "Splat APInt should be element width");
4768 if (N1IsConst && ConstValue1.
isZero())
4772 if (N1IsConst && ConstValue1.
isOne())
4776 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4780 if (N1IsConst && ConstValue1.
isAllOnes())
4786 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
4790 Flags.setNoUnsignedWrap(
N->getFlags().hasNoUnsignedWrap());
4792 return Matcher.getNode(
ISD::SHL,
DL, VT, N0, Trunc, Flags);
4798 unsigned Log2Val = (-ConstValue1).logBase2();
4802 return Matcher.getNode(
4813 SDVTList LoHiVT = DAG.
getVTList(VT, VT);
4816 if (LoHi->hasAnyUseOfValue(1))
4819 if (LoHi->hasAnyUseOfValue(1))
4840 if (!UseVP && N1IsConst &&
4846 APInt MulC = ConstValue1.
abs();
4848 unsigned TZeros = MulC == 2 ? 0 : MulC.
countr_zero();
4850 if ((MulC - 1).isPowerOf2())
4852 else if ((MulC + 1).isPowerOf2())
4857 MathOp ==
ISD::ADD ? (MulC - 1).logBase2() : (MulC + 1).logBase2();
4860 "multiply-by-constant generated out of bounds shift");
4864 TZeros ? DAG.
getNode(MathOp,
DL, VT, Shl,
4906 return Matcher.getNode(
4924 APInt NewStep = C0 * MulVal;
4930 if (!UseVP && (!LegalOperations || hasOperation(
ISD::ABS, VT)) &&
4944 SmallBitVector ClearMask;
4946 auto IsClearMask = [&ClearMask](ConstantSDNode *
V) {
4947 if (!V ||
V->isZero()) {
4961 for (
unsigned I = 0;
I != NumElts; ++
I)
4992 EVT NodeType =
Node->getValueType(0);
4993 if (!NodeType.isSimple())
4995 switch (NodeType.getSimpleVT().SimpleTy) {
4996 default:
return false;
4997 case MVT::i8: LC= isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
4998 case MVT::i16: LC= isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
4999 case MVT::i32: LC= isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
5000 case MVT::i64: LC= isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
5001 case MVT::i128: LC= isSigned ? RTLIB::SDIVREM_I128:RTLIB::UDIVREM_I128;
break;
5008SDValue DAGCombiner::useDivRem(SDNode *Node) {
5009 if (
Node->use_empty())
5012 unsigned Opcode =
Node->getOpcode();
5017 EVT VT =
Node->getValueType(0);
5031 unsigned OtherOpcode = 0;
5045 for (SDNode *User : Op0->
users()) {
5052 unsigned UserOpc =
User->getOpcode();
5053 if ((UserOpc == Opcode || UserOpc == OtherOpcode || UserOpc == DivRemOpc) &&
5054 User->getOperand(0) == Op0 &&
5055 User->getOperand(1) == Op1) {
5057 if (UserOpc == OtherOpcode) {
5059 combined = DAG.
getNode(DivRemOpc, SDLoc(Node), VTs, Op0, Op1);
5060 }
else if (UserOpc == DivRemOpc) {
5063 assert(UserOpc == Opcode);
5068 CombineTo(User, combined);
5070 CombineTo(User, combined.
getValue(1));
5079 EVT VT =
N->getValueType(0);
5082 unsigned Opc =
N->getOpcode();
5101 if (N0C && N0C->
isZero())
5121SDValue DAGCombiner::visitSDIV(SDNode *
N) {
5124 EVT VT =
N->getValueType(0);
5134 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5151 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
5159 if (
SDValue V = visitSDIVLike(N0, N1,
N)) {
5166 if (!
N->getFlags().hasExact()) {
5169 AddToWorklist(
Mul.getNode());
5170 AddToWorklist(
Sub.getNode());
5171 CombineTo(RemNode,
Sub);
5192 if (
C->isZero() ||
C->isOpaque())
5194 if (
C->getAPIntValue().isPowerOf2())
5196 if (
C->getAPIntValue().isNegatedPowerOf2())
5207 EVT VT =
N->getValueType(0);
5232 AddToWorklist(Sign.
getNode());
5238 AddToWorklist(
Add.getNode());
5249 Sra = DAG.
getSelect(
DL, VT, IsOneOrAllOnes, N0, Sra);
5275SDValue DAGCombiner::visitUDIV(SDNode *
N) {
5278 EVT VT =
N->getValueType(0);
5288 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5302 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
5305 if (
SDValue V = visitUDIVLike(N0, N1,
N)) {
5312 if (!
N->getFlags().hasExact()) {
5315 AddToWorklist(
Mul.getNode());
5316 AddToWorklist(
Sub.getNode());
5317 CombineTo(RemNode,
Sub);
5342 EVT VT =
N->getValueType(0);
5347 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
5348 AddToWorklist(LogBase2.getNode());
5352 AddToWorklist(Trunc.
getNode());
5362 if (
SDValue LogBase2 = BuildLogBase2(N10,
DL)) {
5363 AddToWorklist(LogBase2.getNode());
5367 AddToWorklist(Trunc.
getNode());
5369 AddToWorklist(
Add.getNode());
5397SDValue DAGCombiner::visitREM(SDNode *
N) {
5398 unsigned Opcode =
N->getOpcode();
5401 EVT VT =
N->getValueType(0);
5423 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
5436 AddToWorklist(
Add.getNode());
5447 AddToWorklist(
Add.getNode());
5464 if (
SDValue OptimizedRem = buildOptimizedSREM(N0, N1,
N))
5465 return OptimizedRem;
5469 isSigned ? visitSDIVLike(N0, N1,
N) : visitUDIVLike(N0, N1,
N);
5472 unsigned DivOpcode = isSigned ? ISD::SDIV : ISD::UDIV;
5473 if (SDNode *DivNode = DAG.getNodeIfExists(DivOpcode, N->getVTList(),
5475 CombineTo(DivNode, OptimizedDiv);
5478 AddToWorklist(OptimizedDiv.
getNode());
5479 AddToWorklist(
Mul.getNode());
5486 return DivRem.getValue(1);
5509SDValue DAGCombiner::visitMULHS(SDNode *
N) {
5512 EVT VT =
N->getValueType(0);
5525 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5568SDValue DAGCombiner::visitMULHU(SDNode *
N) {
5571 EVT VT =
N->getValueType(0);
5584 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5609 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
5624 unsigned SimpleSize =
Simple.getSizeInBits();
5645SDValue DAGCombiner::visitAVG(SDNode *
N) {
5646 unsigned Opcode =
N->getOpcode();
5649 EVT VT =
N->getValueType(0);
5660 return DAG.
getNode(Opcode,
DL,
N->getVTList(), N1, N0);
5663 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5689 X.getValueType() ==
Y.getValueType() &&
5690 hasOperation(Opcode,
X.getValueType())) {
5696 X.getValueType() ==
Y.getValueType() &&
5697 hasOperation(Opcode,
X.getValueType())) {
5730 if (IsSigned &&
Add->getFlags().hasNoSignedWrap())
5733 if (!IsSigned &&
Add->getFlags().hasNoUnsignedWrap())
5747SDValue DAGCombiner::visitABD(SDNode *
N) {
5748 unsigned Opcode =
N->getOpcode();
5751 EVT VT =
N->getValueType(0);
5761 return DAG.
getNode(Opcode,
DL,
N->getVTList(), N1, N0);
5764 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5779 (!LegalOperations || hasOperation(
ISD::ABS, VT)))
5794 EVT SmallVT =
X.getScalarValueSizeInBits() >
Y.getScalarValueSizeInBits()
5797 if (!LegalOperations || hasOperation(Opcode, SmallVT)) {
5812SDValue DAGCombiner::SimplifyNodeWithTwoResults(SDNode *
N,
unsigned LoOp,
5815 bool HiExists =
N->hasAnyUseOfValue(1);
5816 if (!HiExists && (!LegalOperations ||
5819 return CombineTo(
N, Res, Res);
5823 bool LoExists =
N->hasAnyUseOfValue(0);
5824 if (!LoExists && (!LegalOperations ||
5827 return CombineTo(
N, Res, Res);
5831 if (LoExists && HiExists)
5837 AddToWorklist(
Lo.getNode());
5840 (!LegalOperations ||
5842 return CombineTo(
N, LoOpt, LoOpt);
5847 AddToWorklist(
Hi.getNode());
5850 (!LegalOperations ||
5852 return CombineTo(
N, HiOpt, HiOpt);
5858SDValue DAGCombiner::visitSMUL_LOHI(SDNode *
N) {
5864 EVT VT =
N->getValueType(0);
5880 unsigned SimpleSize =
Simple.getSizeInBits();
5892 return CombineTo(
N,
Lo,
Hi);
5899SDValue DAGCombiner::visitUMUL_LOHI(SDNode *
N) {
5905 EVT VT =
N->getValueType(0);
5920 return CombineTo(
N, Zero, Zero);
5926 return CombineTo(
N, N0, Zero);
5933 unsigned SimpleSize =
Simple.getSizeInBits();
5945 return CombineTo(
N,
Lo,
Hi);
5952SDValue DAGCombiner::visitMULO(SDNode *
N) {
5958 EVT CarryVT =
N->getValueType(1);
5979 return DAG.
getNode(
N->getOpcode(),
DL,
N->getVTList(), N1, N0);
5991 N->getVTList(), N0, N0);
5998 return CombineTo(
N,
And, Cmp);
6036 unsigned Opcode0 = isSignedMinMax(N0, N1, N2, N3, CC);
6090 unsigned Opcode1 = isSignedMinMax(N00, N01, N02, N03, N0CC);
6091 if (!Opcode1 || Opcode0 == Opcode1)
6101 APInt MinCPlus1 = MinC + 1;
6102 if (-MaxC == MinCPlus1 && MinCPlus1.
isPowerOf2()) {
6108 if (MaxC == 0 && MinC != 0 && MinCPlus1.
isPowerOf2()) {
6159 unsigned BW = (C1 + 1).exactLogBase2();
6175SDValue DAGCombiner::visitIMINMAX(SDNode *
N) {
6179 unsigned Opcode =
N->getOpcode();
6195 return C0 > C1 ? N0 : N1;
6197 return C0 > C1 ? N1 : N0;
6203 return DAG.
getNode(Opcode,
DL, VT, N1, N0);
6207 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
6211 if (
SDValue RMINMAX = reassociateOps(Opcode,
DL, N0, N1,
N->getFlags()))
6231 return DAG.
getNode(AltOpcode,
DL, VT, N0, N1);
6243 auto ReductionOpcode = [](
unsigned Opcode) {
6257 if (
SDValue SD = reassociateReduction(ReductionOpcode(Opcode), Opcode,
6258 SDLoc(
N), VT, N0, N1))
6270SDValue DAGCombiner::hoistLogicOpWithSameOpcodeHands(SDNode *
N) {
6273 unsigned LogicOpcode =
N->getOpcode();
6298 if (XVT !=
Y.getValueType())
6302 if ((VT.
isVector() || LegalOperations) &&
6312 SDNodeFlags LogicFlags;
6318 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6328 if (XVT !=
Y.getValueType())
6340 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6361 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6376 return DAG.
getNode(HandOpcode,
DL, VT, Logic0, Logic1, S);
6389 if (XVT.
isInteger() && XVT ==
Y.getValueType() &&
6393 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6412 assert(
X.getValueType() ==
Y.getValueType() &&
6413 "Inputs to shuffles are not the same type");
6419 if (!SVN0->hasOneUse() || !SVN1->hasOneUse() ||
6420 !SVN0->getMask().equals(SVN1->getMask()))
6456 SDValue LL, LR, RL, RR, N0CC, N1CC;
6457 if (!isSetCCEquivalent(N0, LL, LR, N0CC) ||
6458 !isSetCCEquivalent(N1, RL, RR, N1CC))
6462 "Unexpected operand types for bitwise logic op");
6465 "Unexpected operand types for setcc");
6481 if (LR == RR && CC0 == CC1 && IsInteger) {
6486 bool AndEqZero = IsAnd && CC1 ==
ISD::SETEQ && IsZero;
6488 bool AndGtNeg1 = IsAnd && CC1 ==
ISD::SETGT && IsNeg1;
6490 bool OrNeZero = !IsAnd && CC1 ==
ISD::SETNE && IsZero;
6492 bool OrLtZero = !IsAnd && CC1 ==
ISD::SETLT && IsZero;
6498 if (AndEqZero || AndGtNeg1 || OrNeZero || OrLtZero) {
6500 AddToWorklist(
Or.getNode());
6505 bool AndEqNeg1 = IsAnd && CC1 ==
ISD::SETEQ && IsNeg1;
6507 bool AndLtZero = IsAnd && CC1 ==
ISD::SETLT && IsZero;
6509 bool OrNeNeg1 = !IsAnd && CC1 ==
ISD::SETNE && IsNeg1;
6511 bool OrGtNeg1 = !IsAnd && CC1 ==
ISD::SETGT && IsNeg1;
6517 if (AndEqNeg1 || AndLtZero || OrNeNeg1 || OrGtNeg1) {
6519 AddToWorklist(
And.getNode());
6533 AddToWorklist(
Add.getNode());
6554 auto MatchDiffPow2 = [&](ConstantSDNode *C0, ConstantSDNode *C1) {
6560 return !C0->
isOpaque() && !C1->isOpaque() && (CMax - CMin).isPowerOf2();
6578 if (LL == RR && LR == RL) {
6585 if (LL == RL && LR == RR) {
6589 (!LegalOperations ||
6626 SelectionDAG &DAG,
bool isFMAXNUMFMINNUM_IEEE,
bool isFMAXNUMFMINNUM) {
6637 isFMAXNUMFMINNUM_IEEE
6645 isFMAXNUMFMINNUM_IEEE
6663 isFMAXNUMFMINNUM_IEEE
6672 isFMAXNUMFMINNUM_IEEE
6683 (LogicOp->getOpcode() ==
ISD::AND || LogicOp->getOpcode() ==
ISD::OR) &&
6684 "Invalid Op to combine SETCC with");
6690 !
LHS->hasOneUse() || !
RHS->hasOneUse())
6695 LogicOp,
LHS.getNode(),
RHS.getNode());
6707 EVT VT = LogicOp->getValueType(0);
6730 (isFMAXNUMFMINNUM_IEEE || isFMAXNUMFMINNUM))) &&
6736 SDValue CommonValue, Operand1, Operand2;
6744 }
else if (LHS1 == RHS1) {
6757 }
else if (RHS0 == LHS1) {
6774 bool IsSigned = isSignedIntSetCC(CC);
6778 bool IsOr = (LogicOp->getOpcode() ==
ISD::OR);
6785 Operand1, Operand2, CC, LogicOp->
getOpcode(), DAG,
6786 isFMAXNUMFMINNUM_IEEE, isFMAXNUMFMINNUM);
6790 DAG.
getNode(NewOpcode,
DL, OpVT, Operand1, Operand2);
6791 return DAG.
getSetCC(
DL, VT, MinMaxValue, CommonValue, CC);
6796 if (LHS0 == LHS1 && RHS0 == RHS1 && CCL == CCR &&
6800 return DAG.
getSetCC(
DL, VT, LHS0, RHS0, CCL);
6807 LHS0 == RHS0 && LHS1C && RHS1C && OpVT.
isInteger()) {
6808 const APInt &APLhs = LHS1C->getAPIntValue();
6809 const APInt &APRhs = RHS1C->getAPIntValue();
6813 if (APLhs == (-APRhs) &&
6824 }
else if (TargetPreference &
6845 APInt Dif = MaxC - MinC;
6879 EVT CondVT =
Cond.getValueType();
6890 EVT OpVT =
T.getValueType();
6909 if (
SDValue V = foldLogicOfSetCCs(
true, N0, N1,
DL))
6926 APInt
ADDC = ADDI->getAPIntValue();
6927 APInt SRLC = SRLI->getAPIntValue();
6939 CombineTo(N0.
getNode(), NewAdd);
6952bool DAGCombiner::isAndLoadExtLoad(ConstantSDNode *AndC, LoadSDNode *LoadN,
6953 EVT LoadResultTy, EVT &ExtVT) {
6962 if (ExtVT == LoadedVT &&
6963 (!LegalOperations ||
6979 if (LegalOperations &&
6989bool DAGCombiner::isLegalNarrowLdSt(LSBaseSDNode *LDST,
6998 const unsigned ByteShAmt = ShAmt / 8;
7017 if (LdStMemVT.
bitsLT(MemVT))
7032 if (PtrType == MVT::Untyped || PtrType.
isExtended())
7039 if (!
SDValue(Load, 0).hasOneUse())
7042 if (LegalOperations &&
7051 if (
Load->getNumValues() > 2)
7070 if (LegalOperations &&
7077bool DAGCombiner::SearchForAndLoads(SDNode *
N,
7078 SmallVectorImpl<LoadSDNode*> &Loads,
7079 SmallPtrSetImpl<SDNode*> &NodesWithConsts,
7080 ConstantSDNode *Mask,
7081 SDNode *&NodeToMask) {
7085 if (
Op.getValueType().isVector())
7091 "Expected bitwise logic operation");
7092 if (!
C->getAPIntValue().isSubsetOf(
Mask->getAPIntValue()))
7097 if (!
Op.hasOneUse())
7100 switch(
Op.getOpcode()) {
7104 if (isAndLoadExtLoad(Mask, Load,
Load->getValueType(0), ExtVT) &&
7122 unsigned ActiveBits =
Mask->getAPIntValue().countr_one();
7126 Op.getOperand(0).getValueType();
7137 if (!SearchForAndLoads(
Op.getNode(), Loads, NodesWithConsts, Mask,
7148 NodeToMask =
Op.getNode();
7151 for (
unsigned i = 0, e = NodeToMask->
getNumValues(); i < e; ++i) {
7152 MVT VT =
SDValue(NodeToMask, i).getSimpleValueType();
7153 if (VT != MVT::Glue && VT != MVT::Other) {
7155 NodeToMask =
nullptr;
7167bool DAGCombiner::BackwardsPropagateMask(SDNode *
N) {
7172 if (!
Mask->getAPIntValue().isMask())
7180 SmallPtrSet<SDNode*, 2> NodesWithConsts;
7181 SDNode *FixupNode =
nullptr;
7182 if (SearchForAndLoads(
N, Loads, NodesWithConsts, Mask, FixupNode)) {
7195 SDValue(FixupNode, 0), MaskOp);
7197 if (
And.getOpcode() == ISD ::AND)
7202 for (
auto *LogicN : NodesWithConsts) {
7208 if (LogicN->getOpcode() ==
ISD::AND &&
7227 for (
auto *Load : Loads) {
7232 if (
And.getOpcode() == ISD ::AND)
7235 SDValue NewLoad = reduceLoadWidth(
And.getNode());
7237 "Shouldn't be masking the load if it can't be narrowed");
7238 CombineTo(Load, NewLoad, NewLoad.
getValue(1));
7251SDValue DAGCombiner::unfoldExtremeBitClearingToShifts(SDNode *
N) {
7262 unsigned OuterShift;
7263 unsigned InnerShift;
7265 auto matchMask = [&OuterShift, &InnerShift, &
Y](
SDValue M) ->
bool {
7268 OuterShift =
M->getOpcode();
7277 Y =
M->getOperand(1);
7284 else if (matchMask(N0))
7290 EVT VT =
N->getValueType(0);
7307 SDValue And0 =
And->getOperand(0), And1 =
And->getOperand(1);
7317 bool FoundNot =
false;
7320 Src = Src.getOperand(0);
7326 Src = Src.getOperand(0);
7330 if (Src.getOpcode() !=
ISD::SRL || !Src.hasOneUse())
7334 EVT SrcVT = Src.getValueType();
7343 if (!ShiftAmtC || !ShiftAmtC->getAPIntValue().ult(
BitWidth))
7347 Src = Src.getOperand(0);
7354 Src = Src.getOperand(0);
7378 EVT VT =
N->getValueType(0);
7404 unsigned LogicOpcode =
N->getOpcode();
7406 "Expected bitwise logic operation");
7408 if (!LogicOp.hasOneUse() || !ShiftOp.
hasOneUse())
7412 unsigned ShiftOpcode = ShiftOp.
getOpcode();
7413 if (LogicOp.getOpcode() != LogicOpcode ||
7425 if (LogicOp.getOperand(0).getOpcode() == ShiftOpcode &&
7426 LogicOp.getOperand(0).getOperand(1) ==
Y) {
7428 Z = LogicOp.getOperand(1);
7429 }
else if (LogicOp.getOperand(1).getOpcode() == ShiftOpcode &&
7430 LogicOp.getOperand(1).getOperand(1) ==
Y) {
7432 Z = LogicOp.getOperand(0);
7437 EVT VT =
N->getValueType(0);
7441 return DAG.
getNode(LogicOpcode,
DL, VT, NewShift, Z);
7452 unsigned LogicOpcode =
N->getOpcode();
7454 "Expected bitwise logic operation");
7455 if (LeftHand.
getOpcode() != LogicOpcode ||
7476 EVT VT =
N->getValueType(0);
7478 return DAG.
getNode(LogicOpcode,
DL, VT, CombinedShifts, W);
7490 "Must be called with ISD::OR or ISD::AND node");
7504 EVT VT = M.getValueType();
7512SDValue DAGCombiner::visitAND(SDNode *
N) {
7536 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
7554 EVT MemVT =
MLoad->getMemoryVT();
7564 MLoad->isExpandingLoad());
7565 CombineTo(
N, Frozen ? N0 : NewLoad);
7566 CombineTo(MLoad, NewLoad, NewLoad.
getValue(1));
7586 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
7599 auto MatchSubset = [](ConstantSDNode *
LHS, ConstantSDNode *
RHS) {
7600 return RHS->getAPIntValue().isSubsetOf(
LHS->getAPIntValue());
7610 APInt
Mask = ~N1C->getAPIntValue();
7635 {N0Op0.getOperand(1)})) {
7668 unsigned EltBitWidth =
Vector->getValueType(0).getScalarSizeInBits();
7669 APInt SplatValue, SplatUndef;
7670 unsigned SplatBitSize;
7677 const bool IsBigEndian =
false;
7679 Vector->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
7680 HasAnyUndefs, EltBitWidth, IsBigEndian);
7684 if (IsSplat && (SplatBitSize % EltBitWidth) == 0) {
7687 SplatValue |= SplatUndef;
7694 for (
unsigned i = 0, n = (SplatBitSize / EltBitWidth); i < n; ++i)
7695 Constant &= SplatValue.
extractBits(EltBitWidth, i * EltBitWidth);
7703 Load->getValueType(0),
7704 Load->getMemoryVT());
7712 switch (
Load->getExtensionType()) {
7713 default:
B =
false;
break;
7725 CombineTo(
N, (N0.
getNode() == Load) ? NewLoad : N0);
7729 Load->getValueType(0), SDLoc(Load),
7730 Load->getChain(),
Load->getBasePtr(),
7731 Load->getOffset(),
Load->getMemoryVT(),
7732 Load->getMemOperand());
7734 if (
Load->getNumValues() == 3) {
7736 SDValue To[] = { NewLoad.getValue(0), NewLoad.getValue(1),
7737 NewLoad.getValue(2) };
7738 CombineTo(Load, To, 3,
true);
7740 CombineTo(Load, NewLoad.getValue(0), NewLoad.getValue(1));
7750 if (
SDValue Shuffle = XformToShuffleWithZero(
N))
7777 EVT MemVT = GN0->getMemoryVT();
7780 if (
SDValue(GN0, 0).hasOneUse() &&
7783 SDValue Ops[] = {GN0->getChain(), GN0->getPassThru(), GN0->getMask(),
7784 GN0->getBasePtr(), GN0->getIndex(), GN0->getScale()};
7787 DAG.
getVTList(VT, MVT::Other), MemVT,
DL,
Ops, GN0->getMemOperand(),
7790 CombineTo(
N, ZExtLoad);
7791 AddToWorklist(ZExtLoad.
getNode());
7800 if (
SDValue Res = reduceLoadWidth(
N))
7808 if (BackwardsPropagateMask(
N))
7812 if (
SDValue Combined = visitANDLike(N0, N1,
N))
7817 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
7848 if (
SDValue Folded = foldBitwiseOpWithNeg(
N,
DL, VT))
7870 X.getOperand(0).getScalarValueSizeInBits() == 1)
7873 X.getOperand(0).getScalarValueSizeInBits() == 1)
7888 EVT MemVT = LN0->getMemoryVT();
7895 ((!LegalOperations && LN0->isSimple()) ||
7899 LN0->getBasePtr(), MemVT, LN0->getMemOperand());
7913 if (
SDValue Shifts = unfoldExtremeBitClearingToShifts(
N))
7933 if (!
C->getAPIntValue().isMask(
7934 LHS.getOperand(0).getValueType().getFixedSizeInBits()))
7941 if (IsAndZeroExtMask(N0, N1))
7950 if (LegalOperations || VT.
isVector())
7963 bool DemandHighBits) {
7964 if (!LegalOperations)
7967 EVT VT =
N->getValueType(0);
7968 if (VT != MVT::i64 && VT != MVT::i32 && VT != MVT::i16)
7974 bool LookPassAnd0 =
false;
7975 bool LookPassAnd1 =
false;
7990 LookPassAnd0 =
true;
8000 LookPassAnd1 =
true;
8026 LookPassAnd0 =
true;
8040 LookPassAnd1 =
true;
8049 if (OpSizeInBits > 16) {
8053 if (DemandHighBits && !LookPassAnd0)
8060 if (!LookPassAnd1) {
8061 unsigned HighBit = DemandHighBits ? OpSizeInBits : 24;
8069 if (OpSizeInBits > 16) {
8084 if (!
N->hasOneUse())
8087 unsigned Opc =
N.getOpcode();
8105 unsigned MaskByteOffset;
8109 case 0xFF: MaskByteOffset = 0;
break;
8110 case 0xFF00: MaskByteOffset = 1;
break;
8119 case 0xFF0000: MaskByteOffset = 2;
break;
8120 case 0xFF000000: MaskByteOffset = 3;
break;
8125 if (MaskByteOffset == 0 || MaskByteOffset == 2) {
8131 if (!
C ||
C->getZExtValue() != 8)
8139 if (!
C ||
C->getZExtValue() != 8)
8145 if (MaskByteOffset != 0 && MaskByteOffset != 2)
8148 if (!
C ||
C->getZExtValue() != 8)
8153 if (MaskByteOffset != 1 && MaskByteOffset != 3)
8156 if (!
C ||
C->getZExtValue() != 8)
8160 if (Parts[MaskByteOffset])
8175 if (!
C ||
C->getAPIntValue() != 16)
8177 Parts[0] = Parts[1] =
N.getOperand(0).getOperand(0).getNode();
8192 "MatchBSwapHWordOrAndAnd: expecting i32");
8202 if (!Mask0 || !Mask1)
8213 if (!ShiftAmt0 || !ShiftAmt1)
8233 if (!LegalOperations)
8236 EVT VT =
N->getValueType(0);
8254 SDNode *Parts[4] = {};
8274 if (Parts[0] != Parts[1] || Parts[0] != Parts[2] || Parts[0] != Parts[3])
8302 if (
SDValue V = foldLogicOfSetCCs(
false, N0, N1,
DL))
8311 if (
const ConstantSDNode *N0O1C =
8313 if (
const ConstantSDNode *N1O1C =
8317 const APInt &LHSMask = N0O1C->getAPIntValue();
8318 const APInt &RHSMask = N1O1C->getAPIntValue();
8352 auto peekThroughResize = [](
SDValue V) {
8354 return V->getOperand(0);
8358 SDValue N0Resized = peekThroughResize(N0);
8360 SDValue N1Resized = peekThroughResize(N1);
8365 if (N00 == N1Resized || N01 == N1Resized)
8372 if (peekThroughResize(NotOperand) == N1Resized)
8380 if (peekThroughResize(NotOperand) == N1Resized)
8401 auto peekThroughZext = [](
SDValue V) {
8403 return V->getOperand(0);
8425 Lo.getScalarValueSizeInBits() == (BW / 2) &&
8426 Lo.getValueType() ==
Hi.getValueType()) {
8442SDValue DAGCombiner::visitOR(SDNode *
N) {
8463 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
8485 if ((ZeroN00 != ZeroN01) && (ZeroN10 != ZeroN11)) {
8486 assert((!ZeroN00 || !ZeroN01) &&
"Both inputs zero!");
8487 assert((!ZeroN10 || !ZeroN11) &&
"Both inputs zero!");
8488 bool CanFold =
true;
8490 SmallVector<int, 4>
Mask(NumElts, -1);
8492 for (
int i = 0; i != NumElts; ++i) {
8493 int M0 = SV0->getMaskElt(i);
8494 int M1 = SV1->getMaskElt(i);
8497 bool M0Zero =
M0 < 0 || (ZeroN00 == (
M0 < NumElts));
8498 bool M1Zero =
M1 < 0 || (ZeroN10 == (
M1 < NumElts));
8502 if ((M0Zero &&
M1 < 0) || (M1Zero &&
M0 < 0))
8506 if (M0Zero == M1Zero) {
8511 assert((
M0 >= 0 ||
M1 >= 0) &&
"Undef index!");
8517 Mask[i] = M1Zero ?
M0 % NumElts : (
M1 % NumElts) + NumElts;
8526 return LegalShuffle;
8540 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
8551 if (
SDValue Combined = visitORLike(N0, N1,
DL))
8558 if (
SDValue BSwap = MatchBSwapHWord(
N, N0, N1))
8560 if (
SDValue BSwap = MatchBSwapHWordLow(
N, N0, N1))
8574 auto MatchIntersect = [](ConstantSDNode *C1, ConstantSDNode *C2) {
8594 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
8598 if (
SDValue Rot = MatchRotate(N0, N1,
DL,
false))
8601 if (
SDValue Load = MatchLoadCombine(
N))
8611 if (
SDValue Combined = visitADDLike(
N))
8616 if (LegalOperations || VT.
isVector())
8631 Mask =
Op.getOperand(1);
8632 return Op.getOperand(0);
8675 assert(OppShift && ExtractFrom &&
"Empty SDValue");
8703 bool IsMulOrDiv =
false;
8706 auto SelectOpcode = [&](
unsigned NeededShift,
unsigned MulOrDivVariant) {
8707 IsMulOrDiv = ExtractFrom.
getOpcode() == MulOrDivVariant;
8708 if (!IsMulOrDiv && ExtractFrom.
getOpcode() != NeededShift)
8710 Opcode = NeededShift;
8760 if (Rem != 0 || ResultAmt != OppLHSAmt)
8766 if (OppLHSAmt != ExtractFromAmt - NeededShiftAmt.
zextOrTrunc(
8775 return DAG.
getNode(Opcode,
DL, ResVT, OppShiftLHS, NewShiftNode);
8829 unsigned MaskLoBits = 0;
8831 unsigned Bits =
Log2_64(EltSize);
8833 if (NegBits >= Bits) {
8856 if (PosBits >= MaskLoBits) {
8878 if ((Pos == NegOp1) ||
8902 return Width.
getLoBits(MaskLoBits) == 0;
8903 return Width == EltSize;
8913 SDValue InnerNeg,
bool FromAdd,
8914 bool HasPos,
unsigned PosOpcode,
8915 unsigned NegOpcode,
const SDLoc &
DL) {
8926 return DAG.
getNode(HasPos ? PosOpcode : NegOpcode,
DL, VT, Shifted,
8927 HasPos ? Pos : Neg);
8940 SDValue InnerNeg,
bool FromAdd,
8941 bool HasPos,
unsigned PosOpcode,
8942 unsigned NegOpcode,
const SDLoc &
DL) {
8955 return DAG.
getNode(HasPos ? PosOpcode : NegOpcode,
DL, VT, N0, N1,
8956 HasPos ? Pos : Neg);
9001 EVT VT =
LHS.getValueType();
9006 bool HasROTL = hasOperation(
ISD::ROTL, VT);
9007 bool HasROTR = hasOperation(
ISD::ROTR, VT);
9008 bool HasFSHL = hasOperation(
ISD::FSHL, VT);
9009 bool HasFSHR = hasOperation(
ISD::FSHR, VT);
9020 if (LegalOperations && !HasROTL && !HasROTR && !HasFSHL && !HasFSHR)
9025 LHS.getOperand(0).getValueType() ==
RHS.getOperand(0).getValueType()) {
9028 MatchRotate(
LHS.getOperand(0),
RHS.getOperand(0),
DL, FromAdd))
9042 if (!LHSShift && !RHSShift)
9057 RHSShift = NewRHSShift;
9062 LHSShift = NewLHSShift;
9065 if (!RHSShift || !LHSShift)
9090 auto MatchRotateSum = [EltSizeInBits](ConstantSDNode *
LHS,
9091 ConstantSDNode *
RHS) {
9092 return (
LHS->getAPIntValue() +
RHS->getAPIntValue()) == EltSizeInBits;
9095 auto ApplyMasks = [&](
SDValue Res) {
9119 bool IsRotate = LHSShiftArg == RHSShiftArg;
9120 if (!IsRotate && !(HasFSHL || HasFSHR)) {
9129 if (CommonOp ==
Or.getOperand(0)) {
9131 Y =
Or.getOperand(1);
9134 if (CommonOp ==
Or.getOperand(1)) {
9136 Y =
Or.getOperand(0);
9143 if (matchOr(LHSShiftArg, RHSShiftArg)) {
9148 }
else if (matchOr(RHSShiftArg, LHSShiftArg)) {
9157 return ApplyMasks(Res);
9170 if (IsRotate && (HasROTL || HasROTR || !(HasFSHL || HasFSHR))) {
9171 bool UseROTL = !LegalOperations || HasROTL;
9173 UseROTL ? LHSShiftAmt : RHSShiftAmt);
9175 bool UseFSHL = !LegalOperations || HasFSHL;
9177 RHSShiftArg, UseFSHL ? LHSShiftAmt : RHSShiftAmt);
9180 return ApplyMasks(Res);
9185 if (!HasROTL && !HasROTR && !HasFSHL && !HasFSHR)
9194 SDValue LExtOp0 = LHSShiftAmt;
9195 SDValue RExtOp0 = RHSShiftAmt;
9208 if (IsRotate && (HasROTL || HasROTR)) {
9209 if (
SDValue TryL = MatchRotatePosNeg(LHSShiftArg, LHSShiftAmt, RHSShiftAmt,
9210 LExtOp0, RExtOp0, FromAdd, HasROTL,
9214 if (
SDValue TryR = MatchRotatePosNeg(RHSShiftArg, RHSShiftAmt, LHSShiftAmt,
9215 RExtOp0, LExtOp0, FromAdd, HasROTR,
9220 if (
SDValue TryL = MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, LHSShiftAmt,
9221 RHSShiftAmt, LExtOp0, RExtOp0, FromAdd,
9225 if (
SDValue TryR = MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, RHSShiftAmt,
9226 LHSShiftAmt, RExtOp0, LExtOp0, FromAdd,
9276static std::optional<SDByteProvider>
9278 std::optional<uint64_t> VectorIndex,
9279 unsigned StartingIndex = 0) {
9283 return std::nullopt;
9287 if (
Depth && !
Op.hasOneUse() &&
9288 (
Op.getOpcode() !=
ISD::LOAD || !
Op.getValueType().isVector()))
9289 return std::nullopt;
9293 if (
Op.getOpcode() !=
ISD::LOAD && VectorIndex.has_value())
9294 return std::nullopt;
9296 unsigned BitWidth =
Op.getScalarValueSizeInBits();
9298 return std::nullopt;
9300 assert(Index < ByteWidth &&
"invalid index requested");
9303 switch (
Op.getOpcode()) {
9308 return std::nullopt;
9312 return std::nullopt;
9314 if (
LHS->isConstantZero())
9316 if (
RHS->isConstantZero())
9318 return std::nullopt;
9323 return std::nullopt;
9325 uint64_t BitShift = ShiftOp->getZExtValue();
9327 if (BitShift % 8 != 0)
9328 return std::nullopt;
9334 return Index < ByteShift
9337 Depth + 1, VectorIndex, Index);
9344 if (NarrowBitWidth % 8 != 0)
9345 return std::nullopt;
9346 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
9348 if (Index >= NarrowByteWidth)
9350 ? std::optional<SDByteProvider>(
9358 Depth + 1, VectorIndex, StartingIndex);
9362 return std::nullopt;
9364 VectorIndex =
OffsetOp->getZExtValue();
9368 if (NarrowBitWidth % 8 != 0)
9369 return std::nullopt;
9370 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
9373 if (Index >= NarrowByteWidth)
9374 return std::nullopt;
9382 if (*VectorIndex * NarrowByteWidth > StartingIndex)
9383 return std::nullopt;
9384 if ((*VectorIndex + 1) * NarrowByteWidth <= StartingIndex)
9385 return std::nullopt;
9388 VectorIndex, StartingIndex);
9392 if (!L->isSimple() || L->isIndexed())
9393 return std::nullopt;
9395 unsigned NarrowBitWidth = L->getMemoryVT().getScalarSizeInBits();
9396 if (NarrowBitWidth % 8 != 0)
9397 return std::nullopt;
9398 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
9403 if (Index >= NarrowByteWidth)
9405 ? std::optional<SDByteProvider>(
9409 unsigned BPVectorIndex = VectorIndex.value_or(0U);
9414 return std::nullopt;
9429 int64_t FirstOffset) {
9431 unsigned Width = ByteOffsets.
size();
9433 return std::nullopt;
9435 bool BigEndian =
true, LittleEndian =
true;
9436 for (
unsigned i = 0; i < Width; i++) {
9437 int64_t CurrentByteOffset = ByteOffsets[i] - FirstOffset;
9440 if (!BigEndian && !LittleEndian)
9441 return std::nullopt;
9444 assert((BigEndian != LittleEndian) &&
"It should be either big endian or"
9451 switch (
Value.getOpcode()) {
9456 return Value.getOperand(0);
9483SDValue DAGCombiner::mergeTruncStores(StoreSDNode *
N) {
9494 EVT MemVT =
N->getMemoryVT();
9495 if (!(MemVT == MVT::i8 || MemVT == MVT::i16 || MemVT == MVT::i32) ||
9496 !
N->isSimple() ||
N->isIndexed())
9503 unsigned MaxWideNumBits = 64;
9504 unsigned MaxStores = MaxWideNumBits / NarrowNumBits;
9513 if (
Store->getMemoryVT() != MemVT || !
Store->isSimple() ||
9517 Chain =
Store->getChain();
9518 if (MaxStores < Stores.
size())
9522 if (Stores.
size() < 2)
9527 unsigned NumStores = Stores.
size();
9528 unsigned WideNumBits = NumStores * NarrowNumBits;
9529 if (WideNumBits != 16 && WideNumBits != 32 && WideNumBits != 64)
9537 StoreSDNode *FirstStore =
nullptr;
9538 std::optional<BaseIndexOffset>
Base;
9539 for (
auto *Store : Stores) {
9558 if (ShiftAmtC % NarrowNumBits != 0)
9565 Offset = ShiftAmtC / NarrowNumBits;
9571 SourceValue = WideVal;
9572 else if (SourceValue != WideVal) {
9580 SourceValue = WideVal;
9589 int64_t ByteOffsetFromBase = 0;
9592 else if (!
Base->equalBaseIndex(Ptr, DAG, ByteOffsetFromBase))
9596 if (ByteOffsetFromBase < FirstOffset) {
9598 FirstOffset = ByteOffsetFromBase;
9604 OffsetMap[
Offset] = ByteOffsetFromBase;
9610 assert(FirstStore &&
"First store must be set");
9617 if (!Allowed || !
Fast)
9622 auto checkOffsets = [&](
bool MatchLittleEndian) {
9623 if (MatchLittleEndian) {
9624 for (
unsigned i = 0; i != NumStores; ++i)
9625 if (OffsetMap[i] != i * (NarrowNumBits / 8) + FirstOffset)
9628 for (
unsigned i = 0, j = NumStores - 1; i != NumStores; ++i, --
j)
9629 if (OffsetMap[j] != i * (NarrowNumBits / 8) + FirstOffset)
9636 bool NeedBswap =
false;
9637 bool NeedRotate =
false;
9640 if (NarrowNumBits == 8 && checkOffsets(Layout.
isBigEndian()))
9642 else if (NumStores == 2 && checkOffsets(Layout.
isBigEndian()))
9651 "Unexpected store value to merge");
9660 }
else if (NeedRotate) {
9661 assert(WideNumBits % 2 == 0 &&
"Unexpected type for rotate");
9705SDValue DAGCombiner::MatchLoadCombine(SDNode *
N) {
9707 "Can only match load combining against OR nodes");
9710 EVT VT =
N->getValueType(0);
9711 if (VT != MVT::i16 && VT != MVT::i32 && VT != MVT::i64)
9717 assert(
P.hasSrc() &&
"Must be a memory byte provider");
9720 unsigned LoadBitWidth =
Load->getMemoryVT().getScalarSizeInBits();
9722 assert(LoadBitWidth % 8 == 0 &&
9723 "can only analyze providers for individual bytes not bit");
9724 unsigned LoadByteWidth = LoadBitWidth / 8;
9729 std::optional<BaseIndexOffset>
Base;
9732 SmallPtrSet<LoadSDNode *, 8> Loads;
9733 std::optional<SDByteProvider> FirstByteProvider;
9739 unsigned ZeroExtendedBytes = 0;
9740 for (
int i = ByteWidth - 1; i >= 0; --i) {
9747 if (
P->isConstantZero()) {
9750 if (++ZeroExtendedBytes != (ByteWidth -
static_cast<unsigned>(i)))
9754 assert(
P->hasSrc() &&
"provenance should either be memory or zero");
9761 else if (Chain != LChain)
9766 int64_t ByteOffsetFromBase = 0;
9775 if (
L->getMemoryVT().isVector()) {
9776 unsigned LoadWidthInBit =
L->getMemoryVT().getScalarSizeInBits();
9777 if (LoadWidthInBit % 8 != 0)
9779 unsigned ByteOffsetFromVector =
P->SrcOffset * LoadWidthInBit / 8;
9780 Ptr.addToOffset(ByteOffsetFromVector);
9786 else if (!
Base->equalBaseIndex(Ptr, DAG, ByteOffsetFromBase))
9790 ByteOffsetFromBase += MemoryByteOffset(*
P);
9791 ByteOffsets[i] = ByteOffsetFromBase;
9794 if (ByteOffsetFromBase < FirstOffset) {
9795 FirstByteProvider =
P;
9796 FirstOffset = ByteOffsetFromBase;
9802 assert(!Loads.
empty() &&
"All the bytes of the value must be loaded from "
9803 "memory, so there must be at least one load which produces the value");
9804 assert(
Base &&
"Base address of the accessed memory location must be set");
9807 bool NeedsZext = ZeroExtendedBytes > 0;
9818 if (LegalOperations &&
9826 ArrayRef(ByteOffsets).drop_back(ZeroExtendedBytes), FirstOffset);
9830 assert(FirstByteProvider &&
"must be set");
9834 if (MemoryByteOffset(*FirstByteProvider) != 0)
9843 bool NeedsBswap = IsBigEndianTarget != *IsBigEndian;
9850 if (NeedsBswap && (LegalOperations || NeedsZext) &&
9856 if (NeedsBswap && NeedsZext && LegalOperations &&
9864 *FirstLoad->getMemOperand(), &
Fast);
9865 if (!Allowed || !
Fast)
9870 Chain, FirstLoad->getBasePtr(),
9871 FirstLoad->getPointerInfo(), MemVT, FirstLoad->getAlign());
9874 for (LoadSDNode *L : Loads)
9904SDValue DAGCombiner::unfoldMaskedMerge(SDNode *
N) {
9911 EVT VT =
N->getValueType(0);
9933 M =
And.getOperand(XorIdx ? 0 : 1);
9939 if (!matchAndXor(N0, 0, N1) && !matchAndXor(N0, 1, N1) &&
9940 !matchAndXor(N1, 0, N0) && !matchAndXor(N1, 1, N0))
9987SDValue DAGCombiner::visitXOR(SDNode *
N) {
10014 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10026 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10047 if (
SDValue Combined = visitADDLike(
N))
10055 isSetCCEquivalent(N0,
LHS,
RHS, CC,
true) &&
10057 N->use_begin()->getUser()->getOpcode() ==
ISD::AND)) {
10059 LHS.getValueType());
10060 if (!LegalOperations ||
10062 switch (N0Opcode) {
10078 CombineTo(
N, SetCC);
10080 recursivelyDeleteUnusedNodes(N0.
getNode());
10096 AddToWorklist(
V.getNode());
10105 if (isOneUseSetCC(N01) || isOneUseSetCC(N00)) {
10110 return DAG.
getNode(NewOpcode,
DL, VT, N00, N01);
10123 return DAG.
getNode(NewOpcode,
DL, VT, N00, N01);
10133 APInt NotYValue = ~YConst->getAPIntValue();
10149 AddToWorklist(NotX.
getNode());
10154 if (!LegalOperations || hasOperation(
ISD::ABS, VT)) {
10158 SDValue A0 =
A.getOperand(0), A1 =
A.getOperand(1);
10160 if ((A0 == S && A1 == S0) || (A1 == S && A0 == S0))
10197 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
10208 if (
SDValue MM = unfoldMaskedMerge(
N))
10277 if (!LogicOp.hasOneUse())
10280 unsigned LogicOpcode = LogicOp.getOpcode();
10286 unsigned ShiftOpcode = Shift->
getOpcode();
10289 assert(C1Node &&
"Expected a shift with constant operand");
10292 const APInt *&ShiftAmtVal) {
10293 if (V.getOpcode() != ShiftOpcode || !V.hasOneUse())
10301 ShiftOp = V.getOperand(0);
10306 if (ShiftAmtVal->getBitWidth() != C1Val.
getBitWidth())
10311 bool Overflow =
false;
10312 APInt NewShiftAmt = C1Val.
uadd_ov(*ShiftAmtVal, Overflow);
10317 if (NewShiftAmt.
uge(V.getScalarValueSizeInBits()))
10325 const APInt *C0Val;
10326 if (matchFirstShift(LogicOp.getOperand(0),
X, C0Val))
10327 Y = LogicOp.getOperand(1);
10328 else if (matchFirstShift(LogicOp.getOperand(1),
X, C0Val))
10329 Y = LogicOp.getOperand(0);
10340 return DAG.
getNode(LogicOpcode,
DL, VT, NewShift1, NewShift2,
10350SDValue DAGCombiner::visitShiftByConstant(SDNode *
N) {
10370 switch (
LHS.getOpcode()) {
10394 if (!IsShiftByConstant && !IsCopyOrSelect)
10397 if (IsCopyOrSelect &&
N->hasOneUse())
10402 EVT VT =
N->getValueType(0);
10404 N->getOpcode(),
DL, VT, {LHS.getOperand(1), N->getOperand(1)})) {
10407 return DAG.
getNode(
LHS.getOpcode(),
DL, VT, NewShift, NewRHS);
10413SDValue DAGCombiner::distributeTruncateThroughAnd(SDNode *
N) {
10418 EVT TruncVT =
N->getValueType(0);
10419 if (
N->hasOneUse() &&
N->getOperand(0).hasOneUse() &&
10427 AddToWorklist(Trunc00.
getNode());
10428 AddToWorklist(Trunc01.
getNode());
10436SDValue DAGCombiner::visitRotate(SDNode *
N) {
10440 EVT VT =
N->getValueType(0);
10455 bool OutOfRange =
false;
10456 auto MatchOutOfRange = [Bitsize, &OutOfRange](ConstantSDNode *
C) {
10457 OutOfRange |=
C->getAPIntValue().uge(Bitsize);
10465 return DAG.
getNode(
N->getOpcode(), dl, VT, N0, Amt);
10470 if (RotAmtC && RotAmtC->getAPIntValue() == 8 &&
10481 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10482 return DAG.
getNode(
N->getOpcode(), dl, VT, N0, NewOp1);
10494 bool SameSide = (
N->getOpcode() == NextOp);
10501 if (Norm1 && Norm2)
10503 CombineOp, dl, ShiftVT, {Norm1, Norm2})) {
10505 {CombinedShift, BitsizeC});
10507 ISD::UREM, dl, ShiftVT, {CombinedShift, BitsizeC});
10509 CombinedShiftNorm);
10516SDValue DAGCombiner::visitSHL(SDNode *
N) {
10533 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10556 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10566 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10572 auto MatchOutOfRange = [OpSizeInBits](ConstantSDNode *
LHS,
10573 ConstantSDNode *
RHS) {
10574 APInt c1 =
LHS->getAPIntValue();
10575 APInt c2 =
RHS->getAPIntValue();
10577 return (c1 + c2).uge(OpSizeInBits);
10582 auto MatchInRange = [OpSizeInBits](ConstantSDNode *
LHS,
10583 ConstantSDNode *
RHS) {
10584 APInt c1 =
LHS->getAPIntValue();
10585 APInt c2 =
RHS->getAPIntValue();
10587 return (c1 + c2).ult(OpSizeInBits);
10609 auto MatchOutOfRange = [OpSizeInBits, InnerBitwidth](ConstantSDNode *
LHS,
10610 ConstantSDNode *
RHS) {
10611 APInt c1 =
LHS->getAPIntValue();
10612 APInt c2 =
RHS->getAPIntValue();
10614 return c2.
uge(OpSizeInBits - InnerBitwidth) &&
10615 (c1 + c2).uge(OpSizeInBits);
10622 auto MatchInRange = [OpSizeInBits, InnerBitwidth](ConstantSDNode *
LHS,
10623 ConstantSDNode *
RHS) {
10624 APInt c1 =
LHS->getAPIntValue();
10625 APInt c2 =
RHS->getAPIntValue();
10627 return c2.
uge(OpSizeInBits - InnerBitwidth) &&
10628 (c1 + c2).ult(OpSizeInBits);
10648 auto MatchEqual = [VT](ConstantSDNode *
LHS, ConstantSDNode *
RHS) {
10649 APInt c1 =
LHS->getAPIntValue();
10650 APInt c2 =
RHS->getAPIntValue();
10660 AddToWorklist(NewSHL.
getNode());
10666 auto MatchShiftAmount = [OpSizeInBits](ConstantSDNode *
LHS,
10667 ConstantSDNode *
RHS) {
10668 const APInt &LHSC =
LHS->getAPIntValue();
10669 const APInt &RHSC =
RHS->getAPIntValue();
10670 return LHSC.
ult(OpSizeInBits) && RHSC.
ult(OpSizeInBits) &&
10742 AddToWorklist(Shl0.
getNode());
10761 {Add.getOperand(1)})) {
10781 if (
SDValue NewSHL = visitShiftByConstant(
N))
10815 Flags.setNoUnsignedWrap(
N->getFlags().hasNoUnsignedWrap() &&
10828 APInt NewStep = C0 << ShlVal;
10843 "SRL or SRA node is required here!");
10852 SDValue ShiftOperand =
N->getOperand(0);
10863 if (!IsSignExt && !IsZeroExt)
10870 auto UserOfLowerBits = [NarrowVTSize](
SDNode *U) {
10875 if (!UShiftAmtSrc) {
10879 return UShiftAmt < NarrowVTSize;
10893 unsigned ActiveBits = IsSignExt
10894 ?
Constant->getAPIntValue().getSignificantBits()
10895 :
Constant->getAPIntValue().getActiveBits();
10896 if (ActiveBits > NarrowVTSize)
10913 "Cannot have a multiply node with two different operand types.");
10924 if (ShiftAmt != NarrowVTSize)
10934 EVT TransformVT = NarrowVT;
10945 bool IsSigned =
N->getOpcode() ==
ISD::SRA;
10952 unsigned Opcode =
N->getOpcode();
10957 EVT VT =
N->getValueType(0);
10976SDValue DAGCombiner::visitSRA(SDNode *
N) {
10998 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
11001 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
11013 auto SumOfShifts = [&](ConstantSDNode *
LHS, ConstantSDNode *
RHS) {
11014 APInt c1 =
LHS->getAPIntValue();
11015 APInt c2 =
RHS->getAPIntValue();
11017 APInt Sum = c1 + c2;
11018 unsigned ShiftSum =
11019 Sum.
uge(OpSizeInBits) ? (OpSizeInBits - 1) : Sum.getZExtValue();
11029 "Expected matchBinaryPredicate to return one element for "
11033 ShiftValue = ShiftValues[0];
11047 APInt Sum = C1 + C2;
11051 return DAG.
getNOT(
DL, NewShift, VT);
11077 if ((ShiftAmt > 0) &&
11087 N->getValueType(0), Trunc);
11104 if (ConstantSDNode *AddC =
11122 DAG.
getConstant(AddC->getAPIntValue().lshr(ShiftAmt).trunc(
11139 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
11156 if (LargeShift->getAPIntValue() == TruncBits) {
11177 if (
SDValue NewSRA = visitShiftByConstant(
N))
11186 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
11195SDValue DAGCombiner::visitSRL(SDNode *
N) {
11212 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
11215 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
11226 auto MatchOutOfRange = [OpSizeInBits](ConstantSDNode *
LHS,
11227 ConstantSDNode *
RHS) {
11228 APInt c1 =
LHS->getAPIntValue();
11229 APInt c2 =
RHS->getAPIntValue();
11231 return (c1 + c2).uge(OpSizeInBits);
11236 auto MatchInRange = [OpSizeInBits](ConstantSDNode *
LHS,
11237 ConstantSDNode *
RHS) {
11238 APInt c1 =
LHS->getAPIntValue();
11239 APInt c2 =
RHS->getAPIntValue();
11241 return (c1 + c2).ult(OpSizeInBits);
11261 if (c1 + OpSizeInBits == InnerShiftSize) {
11262 if (c1 + c2 >= InnerShiftSize)
11272 c1 + c2 < InnerShiftSize) {
11277 OpSizeInBits - c2),
11294 auto MatchShiftAmount = [OpSizeInBits](ConstantSDNode *
LHS,
11295 ConstantSDNode *
RHS) {
11296 const APInt &LHSC =
LHS->getAPIntValue();
11297 const APInt &RHSC =
RHS->getAPIntValue();
11298 return LHSC.
ult(OpSizeInBits) && RHSC.
ult(OpSizeInBits) &&
11340 AddToWorklist(SmallShift.
getNode());
11368 APInt UnknownBits = ~Known.Zero;
11369 if (UnknownBits == 0)
return DAG.
getConstant(1, SDLoc(N0), VT);
11384 AddToWorklist(
Op.getNode());
11393 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
11419 if (
SDValue NewSRL = visitShiftByConstant(
N))
11423 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
11450 if (
N->hasOneUse()) {
11451 SDNode *
User = *
N->user_begin();
11459 AddToWorklist(User);
11473SDValue DAGCombiner::visitFunnelShift(SDNode *
N) {
11474 EVT VT =
N->getValueType(0);
11492 return IsFSHL ? N0 : N1;
11494 auto IsUndefOrZero = [](
SDValue V) {
11503 if (Cst->getAPIntValue().uge(
BitWidth)) {
11504 uint64_t RotAmt = Cst->getAPIntValue().urem(
BitWidth);
11505 return DAG.
getNode(
N->getOpcode(),
DL, VT, N0, N1,
11509 unsigned ShAmt = Cst->getZExtValue();
11511 return IsFSHL ? N0 : N1;
11517 if (IsUndefOrZero(N0))
11521 if (IsUndefOrZero(N1))
11535 if (
LHS &&
RHS &&
LHS->isSimple() &&
RHS->isSimple() &&
11536 LHS->getAddressSpace() ==
RHS->getAddressSpace() &&
11537 (
LHS->hasNUsesOfValue(1, 0) ||
RHS->hasNUsesOfValue(1, 0)) &&
11546 RHS->getAddressSpace(), NewAlign,
11547 RHS->getMemOperand()->getFlags(), &
Fast) &&
11551 AddToWorklist(NewPtr.
getNode());
11553 VT,
DL,
RHS->getChain(), NewPtr,
11554 RHS->getPointerInfo().getWithOffset(PtrOff), NewAlign,
11555 RHS->getMemOperand()->getFlags(),
RHS->getAAInfo());
11583 if (N0 == N1 && hasOperation(RotOpc, VT))
11584 return DAG.
getNode(RotOpc,
DL, VT, N0, N2);
11593SDValue DAGCombiner::visitSHLSAT(SDNode *
N) {
11628SDValue DAGCombiner::foldABSToABD(SDNode *
N,
const SDLoc &
DL) {
11629 EVT SrcVT =
N->getValueType(0);
11632 N =
N->getOperand(0).getNode();
11634 EVT VT =
N->getValueType(0);
11640 SDValue AbsOp0 =
N->getOperand(0);
11677 EVT MaxVT = VT0.
bitsGT(VT1) ? VT0 : VT1;
11678 if ((VT0 == MaxVT || Op0->
hasOneUse()) &&
11680 (!LegalTypes || hasOperation(ABDOpcode, MaxVT))) {
11690 if (!LegalOperations || hasOperation(ABDOpcode, VT)) {
11698SDValue DAGCombiner::visitABS(SDNode *
N) {
11700 EVT VT =
N->getValueType(0);
11733SDValue DAGCombiner::visitBSWAP(SDNode *
N) {
11735 EVT VT =
N->getValueType(0);
11760 if (ShAmt && ShAmt->getAPIntValue().ult(BW) &&
11761 ShAmt->getZExtValue() >= (BW / 2) &&
11762 (ShAmt->getZExtValue() % 16) == 0 && TLI.
isTypeLegal(HalfVT) &&
11764 (!LegalOperations || hasOperation(
ISD::BSWAP, HalfVT))) {
11766 if (uint64_t NewShAmt = (ShAmt->getZExtValue() - (BW / 2)))
11782 if (ShAmt && ShAmt->getAPIntValue().ult(BW) &&
11783 ShAmt->getZExtValue() % 8 == 0) {
11796SDValue DAGCombiner::visitBITREVERSE(SDNode *
N) {
11798 EVT VT =
N->getValueType(0);
11824SDValue DAGCombiner::visitCTLZ(SDNode *
N) {
11826 EVT VT =
N->getValueType(0);
11841SDValue DAGCombiner::visitCTLZ_ZERO_UNDEF(SDNode *
N) {
11843 EVT VT =
N->getValueType(0);
11853SDValue DAGCombiner::visitCTTZ(SDNode *
N) {
11855 EVT VT =
N->getValueType(0);
11870SDValue DAGCombiner::visitCTTZ_ZERO_UNDEF(SDNode *
N) {
11872 EVT VT =
N->getValueType(0);
11882SDValue DAGCombiner::visitCTPOP(SDNode *
N) {
11884 EVT VT =
N->getValueType(0);
11896 const APInt &Amt = AmtC->getAPIntValue();
11897 if (Amt.
ult(NumBits)) {
11931 EVT VT =
LHS.getValueType();
11935 return Flags.hasNoSignedZeros() &&
11937 (Flags.hasNoNaNs() ||
11987SDValue DAGCombiner::foldShiftToAvg(SDNode *
N,
const SDLoc &
DL) {
11988 const unsigned Opcode =
N->getOpcode();
11992 EVT VT =
N->getValueType(0);
11993 bool IsUnsigned = Opcode ==
ISD::SRL;
12004 if (!hasOperation(FloorISD, VT))
12008 if ((IsUnsigned && !
Add->getFlags().hasNoUnsignedWrap()) ||
12009 (!IsUnsigned && !
Add->getFlags().hasNoSignedWrap()))
12012 return DAG.
getNode(FloorISD,
DL,
N->getValueType(0), {A, B});
12018SDValue DAGCombiner::foldBitwiseOpWithNeg(SDNode *
N,
const SDLoc &
DL, EVT VT) {
12019 unsigned Opc =
N->getOpcode();
12038 if ((
LHS == True &&
RHS == False) || (
LHS == False &&
RHS == True))
12044 True, DAG, LegalOperations, ForCodeSize);
12048 HandleSDNode NegTrueHandle(NegTrue);
12056 if (
LHS == NegTrue) {
12060 RHS, DAG, LegalOperations, ForCodeSize);
12062 HandleSDNode NegRHSHandle(NegRHS);
12063 if (NegRHS == False) {
12065 False, CC, TLI, DAG);
12085 EVT VT =
N->getValueType(0);
12087 VT !=
Cond.getOperand(0).getValueType())
12130SDValue DAGCombiner::foldSelectOfConstants(SDNode *
N) {
12134 EVT VT =
N->getValueType(0);
12135 EVT CondVT =
Cond.getValueType();
12146 if (CondVT != MVT::i1 || LegalOperations) {
12161 C1->
isZero() && C2->isOne()) {
12176 assert(CondVT == MVT::i1 && !LegalOperations);
12179 if (C1->
isOne() && C2->isZero())
12187 if (C1->
isZero() && C2->isOne()) {
12194 if (C1->
isZero() && C2->isAllOnes()) {
12207 const APInt &C1Val = C1->getAPIntValue();
12208 const APInt &C2Val = C2->getAPIntValue();
12211 if (C1Val - 1 == C2Val) {
12217 if (C1Val + 1 == C2Val) {
12237 if (C2->isAllOnes()) {
12249template <
class MatchContextClass>
12253 N->getOpcode() == ISD::VP_SELECT) &&
12254 "Expected a (v)(vp.)select");
12256 SDValue T =
N->getOperand(1),
F =
N->getOperand(2);
12257 EVT VT =
N->getValueType(0);
12259 MatchContextClass matcher(DAG, TLI,
N);
12295 EVT VT =
N->getValueType(0);
12359 EVT VT =
LHS.getValueType();
12361 if (LegalOperations && !hasOperation(ABDOpc, VT))
12374 hasOperation(ABDOpc, VT))
12386 hasOperation(ABDOpc, VT))
12420SDValue DAGCombiner::visitSELECT(SDNode *
N) {
12424 EVT VT =
N->getValueType(0);
12427 SDNodeFlags
Flags =
N->getFlags();
12439 if (
SDValue V = foldSelectOfConstants(
N))
12443 if (SimplifySelectOps(
N, N1, N2))
12446 if (VT0 == MVT::i1) {
12455 bool normalizeToSequence =
12464 if (normalizeToSequence || !InnerSelect.
use_empty())
12466 InnerSelect, N2, Flags);
12469 recursivelyDeleteUnusedNodes(InnerSelect.
getNode());
12476 Cond1, N1, N2, Flags);
12477 if (normalizeToSequence || !InnerSelect.
use_empty())
12479 InnerSelect, Flags);
12482 recursivelyDeleteUnusedNodes(InnerSelect.
getNode());
12492 if (!normalizeToSequence) {
12498 if (
SDValue Combined = visitANDLike(N0, N1_0,
N)) {
12511 if (!normalizeToSequence) {
12517 if (
SDValue Combined = visitORLike(N0, N2_0,
DL))
12553 combineMinNumMaxNum(
DL, VT, Cond0, Cond1, N1, N2, CC))
12566 if (
C && NotC &&
C->getAPIntValue() == ~NotC->getAPIntValue()) {
12586 (!LegalOperations &&
12594 if (
SDValue ABD = foldSelectToABD(Cond0, Cond1, N1, N2, CC,
DL))
12597 if (
SDValue NewSel = SimplifySelect(
DL, N0, N1, N2))
12602 if (
SDValue UMin = foldSelectToUMin(Cond0, Cond1, N1, N2, CC,
DL))
12607 if (
SDValue BinOp = foldSelectOfBinops(
N))
12623 EVT VT =
N->getValueType(0);
12631 if (
LHS->getNumOperands() != 2 ||
RHS->getNumOperands() != 2)
12640 for (
int i = 0; i < NumElems / 2; ++i) {
12641 if (
Cond->getOperand(i)->isUndef())
12644 if (BottomHalf ==
nullptr)
12646 else if (
Cond->getOperand(i).getNode() != BottomHalf)
12652 for (
int i = NumElems / 2; i < NumElems; ++i) {
12653 if (
Cond->getOperand(i)->isUndef())
12656 if (TopHalf ==
nullptr)
12658 else if (
Cond->getOperand(i).getNode() != TopHalf)
12662 assert(TopHalf && BottomHalf &&
12663 "One half of the selector was all UNDEFs and the other was all the "
12664 "same value. This should have been addressed before this function.");
12667 BottomHalf->
isZero() ?
RHS->getOperand(0) :
LHS->getOperand(0),
12668 TopHalf->
isZero() ?
RHS->getOperand(1) :
LHS->getOperand(1));
12681 EVT VT = BasePtr.getValueType();
12685 SplatVal.getValueType() == VT) {
12691 if (Index.getOpcode() !=
ISD::ADD)
12718 Index = Index.getOperand(0);
12731 Index = Index.getOperand(0);
12738SDValue DAGCombiner::visitVPSCATTER(SDNode *
N) {
12769SDValue DAGCombiner::visitMSCATTER(SDNode *
N) {
12801SDValue DAGCombiner::visitMSTORE(SDNode *
N) {
12815 MST1->isSimple() && MST1->getBasePtr() == Ptr &&
12818 MST1->getMemoryVT().getStoreSize()) ||
12822 CombineTo(MST1, MST1->getChain());
12839 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
12843 Value.getValueType().isInteger() &&
12846 APInt TruncDemandedBits =
12872 Value.getOperand(0).getValueType());
12882SDValue DAGCombiner::visitVP_STRIDED_STORE(SDNode *
N) {
12884 EVT EltVT = SST->getValue().getValueType().getVectorElementType();
12887 CStride && CStride->getZExtValue() == EltVT.
getStoreSize()) {
12888 return DAG.
getStoreVP(SST->getChain(), SDLoc(
N), SST->getValue(),
12889 SST->getBasePtr(), SST->getOffset(), SST->getMask(),
12890 SST->getVectorLength(), SST->getMemoryVT(),
12891 SST->getMemOperand(), SST->getAddressingMode(),
12892 SST->isTruncatingStore(), SST->isCompressingStore());
12897SDValue DAGCombiner::visitVECTOR_COMPRESS(SDNode *
N) {
12901 SDValue Passthru =
N->getOperand(2);
12904 bool HasPassthru = !Passthru.
isUndef();
12917 unsigned NumSelected = 0;
12919 for (
unsigned I = 0;
I < NumElmts; ++
I) {
12928 Ops.push_back(VecI);
12932 for (
unsigned Rest = NumSelected; Rest < NumElmts; ++Rest) {
12938 Ops.push_back(Val);
12946SDValue DAGCombiner::visitVPGATHER(SDNode *
N) {
12974SDValue DAGCombiner::visitMGATHER(SDNode *
N) {
12987 return CombineTo(
N, PassThru, MGT->
getChain());
13006SDValue DAGCombiner::visitMLOAD(SDNode *
N) {
13022 return CombineTo(
N, NewLd, NewLd.
getValue(1));
13026 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
13032SDValue DAGCombiner::visitMHISTOGRAM(SDNode *
N) {
13042 EVT DataVT =
Index.getValueType();
13060SDValue DAGCombiner::visitPARTIAL_REDUCE_MLA(SDNode *
N) {
13061 if (
SDValue Res = foldPartialReduceMLAMulOp(
N))
13063 if (
SDValue Res = foldPartialReduceAdd(
N))
13079SDValue DAGCombiner::foldPartialReduceMLAMulOp(SDNode *
N) {
13111 RHS.getValueType().getScalarType()));
13119 auto IsIntOrFPExtOpcode = [](
unsigned int Opcode) {
13123 unsigned LHSOpcode =
LHS->getOpcode();
13124 if (!IsIntOrFPExtOpcode(LHSOpcode))
13135 EVT OpVT =
Op.getValueType();
13149 unsigned LHSBits =
LHS.getValueType().getScalarSizeInBits();
13166 ApplyPredicate(
C, LHSExtOp);
13167 return DAG.
getNode(NewOpcode,
DL,
N->getValueType(0), Acc, LHSExtOp,
C);
13170 unsigned RHSOpcode =
RHS->getOpcode();
13171 if (!IsIntOrFPExtOpcode(RHSOpcode))
13198 NewOpc !=
N->getOpcode())
13208 ApplyPredicate(RHSExtOp, LHSExtOp);
13209 return DAG.
getNode(NewOpc,
DL,
N->getValueType(0), Acc, LHSExtOp, RHSExtOp);
13219SDValue DAGCombiner::foldPartialReduceAdd(SDNode *
N) {
13244 if (Op1IsSigned != NodeIsSigned &&
13271 return DAG.
getNode(NewOpcode,
DL,
N->getValueType(0), Acc, UnextOp1,
13275SDValue DAGCombiner::visitVP_STRIDED_LOAD(SDNode *
N) {
13280 CStride && CStride->getZExtValue() == EltVT.
getStoreSize()) {
13282 SLD->getAddressingMode(), SLD->getExtensionType(), SLD->getValueType(0),
13283 SDLoc(
N), SLD->getChain(), SLD->getBasePtr(), SLD->getOffset(),
13284 SLD->getMask(), SLD->getVectorLength(), SLD->getMemoryVT(),
13285 SLD->getMemOperand(), SLD->isExpandingLoad());
13286 return CombineTo(
N, NewLd, NewLd.
getValue(1));
13293SDValue DAGCombiner::foldVSelectOfConstants(SDNode *
N) {
13297 EVT VT =
N->getValueType(0);
13298 if (!
Cond.hasOneUse() ||
Cond.getScalarValueSizeInBits() != 1 ||
13307 bool AllAddOne =
true;
13308 bool AllSubOne =
true;
13310 for (
unsigned i = 0; i != Elts; ++i) {
13333 if (AllAddOne || AllSubOne) {
13360SDValue DAGCombiner::visitVP_SELECT(SDNode *
N) {
13384 EVT CondVT =
Cond.getValueType();
13385 assert(CondVT.
isVector() &&
"Vector select expects a vector selector!");
13393 if (!IsTAllZero && !IsTAllOne && !IsFAllZero && !IsFAllOne)
13397 if (IsTAllZero && IsFAllZero) {
13406 Cond.getOperand(0).getValueType() == VT && VT.
isSimple() &&
13408 TValAPInt.
isOne() &&
13427 if (!IsTAllOne && !IsFAllZero &&
Cond.hasOneUse() &&
13431 if (IsTAllZero || IsFAllOne) {
13444 "Select condition no longer all-sign bits");
13447 if (IsTAllOne && IsFAllZero)
13476SDValue DAGCombiner::visitVSELECT(SDNode *
N) {
13480 EVT VT =
N->getValueType(0);
13513 bool isAbs =
false;
13532 AddToWorklist(Shift.
getNode());
13533 AddToWorklist(
Add.getNode());
13545 if (
SDValue FMinMax = combineMinNumMaxNum(
DL, VT,
LHS,
RHS, N1, N2, CC))
13560 EVT NarrowVT =
LHS.getValueType();
13568 SetCCWidth != 1 && SetCCWidth < WideWidth &&
13614 (OpLHS == CondLHS || OpRHS == CondLHS))
13617 if (OpRHS.getOpcode() == CondRHS.getOpcode() &&
13620 CondLHS == OpLHS) {
13624 auto MatchUADDSAT = [](ConstantSDNode *
Op, ConstantSDNode *
Cond) {
13625 return Cond->getAPIntValue() == ~Op->getAPIntValue();
13666 if (OpLHS ==
LHS) {
13681 auto MatchUSUBSAT = [](ConstantSDNode *
Op, ConstantSDNode *
Cond) {
13682 return (!
Op && !
Cond) ||
13684 Cond->getAPIntValue() == (-
Op->getAPIntValue() - 1));
13720 if (SimplifySelectOps(
N, N1, N2))
13740 if (
SDValue V = foldVSelectOfConstants(
N))
13756SDValue DAGCombiner::visitSELECT_CC(SDNode *
N) {
13777 AddToWorklist(
SCC.getNode());
13782 return SCCC->isZero() ? N3 : N2;
13786 if (
SCC->isUndef())
13792 SCC.getOperand(0),
SCC.getOperand(1), N2, N3,
13793 SCC.getOperand(2),
SCC->getFlags());
13798 if (SimplifySelectOps(
N, N2, N3))
13802 return SimplifySelectCC(
DL, N0, N1, N2, N3, CC);
13805SDValue DAGCombiner::visitSETCC(SDNode *
N) {
13810 N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BRCOND;
13813 EVT VT =
N->getValueType(0);
13820 if (PreferSetCC && Combined.getOpcode() !=
ISD::SETCC) {
13821 SDValue NewSetCC = rebuildSetCC(Combined);
13849 A.getOperand(0) ==
B.getOperand(0);
13853 B.getOperand(0) ==
A;
13856 bool IsRotate =
false;
13859 if (IsAndWithShift(N0, N1)) {
13861 ShiftOrRotate = N1;
13862 }
else if (IsAndWithShift(N1, N0)) {
13864 ShiftOrRotate = N0;
13865 }
else if (IsRotateWithOp(N0, N1)) {
13868 ShiftOrRotate = N1;
13869 }
else if (IsRotateWithOp(N1, N0)) {
13872 ShiftOrRotate = N0;
13875 if (AndOrOp && ShiftOrRotate && ShiftOrRotate.hasOneUse() &&
13880 auto GetAPIntValue = [](
SDValue Op) -> std::optional<APInt> {
13883 if (CNode ==
nullptr)
13884 return std::nullopt;
13887 std::optional<APInt> AndCMask =
13888 IsRotate ? std::nullopt : GetAPIntValue(AndOrOp.
getOperand(1));
13889 std::optional<APInt> ShiftCAmt =
13890 GetAPIntValue(ShiftOrRotate.getOperand(1));
13894 if (ShiftCAmt && (IsRotate || AndCMask) && ShiftCAmt->ult(NumBits)) {
13895 unsigned ShiftOpc = ShiftOrRotate.getOpcode();
13897 bool CanTransform = IsRotate;
13898 if (!CanTransform) {
13900 CanTransform = *ShiftCAmt == (~*AndCMask).
popcount();
13902 CanTransform &= (*ShiftCAmt + AndCMask->popcount()) == NumBits;
13910 OpVT, ShiftOpc, ShiftCAmt->isPowerOf2(), *ShiftCAmt, AndCMask);
13912 if (CanTransform && NewShiftOpc != ShiftOpc) {
13914 DAG.
getNode(NewShiftOpc,
DL, OpVT, ShiftOrRotate.getOperand(0),
13915 ShiftOrRotate.getOperand(1));
13922 NumBits - ShiftCAmt->getZExtValue())
13923 : APInt::getLowBitsSet(NumBits,
13924 NumBits - ShiftCAmt->getZExtValue());
13932 return DAG.
getSetCC(
DL, VT, NewAndOrOp, NewShiftOrRotate,
Cond);
13940SDValue DAGCombiner::visitSETCCCARRY(SDNode *
N) {
13961 if (!
N.hasOneUse())
13990 unsigned Opcode =
N->getOpcode();
13992 EVT VT =
N->getValueType(0);
13995 "Expected EXTEND dag node in input!");
14035 unsigned Opcode =
N->getOpcode();
14037 EVT VT =
N->getValueType(0);
14040 "Expected EXTEND dag node in input!");
14046 return DAG.
getNode(Opcode,
DL, VT, N0);
14065 unsigned FoldOpc = Opcode;
14088 for (
unsigned i = 0; i != NumElts; ++i) {
14090 if (
Op.isUndef()) {
14101 APInt C =
Op->getAsAPIntVal().zextOrTrunc(EVTBits);
14119 bool HasCopyToRegUses =
false;
14134 for (
unsigned i = 0; i != 2; ++i) {
14152 HasCopyToRegUses =
true;
14155 if (HasCopyToRegUses) {
14156 bool BothLiveOut =
false;
14159 BothLiveOut =
true;
14166 return !ExtendNodes.
empty();
14171void DAGCombiner::ExtendSetCCUses(
const SmallVectorImpl<SDNode *> &SetCCs,
14176 for (SDNode *SetCC : SetCCs) {
14179 for (
unsigned j = 0;
j != 2; ++
j) {
14180 SDValue SOp = SetCC->getOperand(j);
14181 if (SOp == OrigLoad)
14182 Ops.push_back(ExtLoad);
14187 Ops.push_back(SetCC->getOperand(2));
14193SDValue DAGCombiner::CombineExtLoad(SDNode *
N) {
14195 EVT DstVT =
N->getValueType(0);
14200 "Unexpected node type (not an extend)!");
14238 EVT SplitSrcVT = SrcVT;
14239 EVT SplitDstVT = DstVT;
14252 const unsigned NumSplits =
14259 for (
unsigned Idx = 0; Idx < NumSplits; Idx++) {
14260 const unsigned Offset = Idx * Stride;
14278 AddToWorklist(NewChain.
getNode());
14280 CombineTo(
N, NewValue);
14286 ExtendSetCCUses(SetCCs, N0, NewValue, (
ISD::NodeType)
N->getOpcode());
14287 CombineTo(N0.
getNode(), Trunc, NewChain);
14293SDValue DAGCombiner::CombineZExtLogicopShiftLoad(SDNode *
N) {
14295 EVT VT =
N->getValueType(0);
14296 EVT OrigVT =
N->getOperand(0).getValueType();
14318 EVT MemVT =
Load->getMemoryVT();
14339 Load->getChain(),
Load->getBasePtr(),
14340 Load->getMemoryVT(),
Load->getMemOperand());
14353 if (
SDValue(Load, 0).hasOneUse()) {
14357 Load->getValueType(0), ExtLoad);
14358 CombineTo(Load, Trunc, ExtLoad.
getValue(1));
14362 recursivelyDeleteUnusedNodes(N0.
getNode());
14371SDValue DAGCombiner::matchVSelectOpSizesWithSetCC(SDNode *Cast) {
14372 unsigned CastOpcode = Cast->
getOpcode();
14376 "Unexpected opcode for vector select narrowing/widening");
14416 bool LegalOperations,
SDNode *
N,
14427 if ((LegalOperations || !LN0->
isSimple() ||
14438 Combiner.recursivelyDeleteUnusedNodes(LN0);
14451 bool NonNegZExt =
false) {
14458 "Unexpected load type or opcode");
14479 bool DoXform =
true;
14492 Combiner.ExtendSetCCUses(SetCCs, N0, ExtLoad, ExtOpc);
14494 bool NoReplaceTrunc =
SDValue(LN0, 0).hasOneUse();
14496 if (NoReplaceTrunc) {
14498 Combiner.recursivelyDeleteUnusedNodes(LN0);
14543 EVT MemoryVT = ALoad->getMemoryVT();
14552 EVT OrigVT = ALoad->getValueType(0);
14555 ExtLoadType,
SDLoc(ALoad), MemoryVT, VT, ALoad->getChain(),
14556 ALoad->getBasePtr(), ALoad->getMemOperand()));
14566 bool LegalOperations) {
14578 EVT VT =
N->getValueType(0);
14579 EVT XVT =
X.getValueType();
14595 return DAG.
getNode(ShiftOpcode,
DL, VT, NotX, ShiftAmount);
14601SDValue DAGCombiner::foldSextSetcc(SDNode *
N) {
14609 EVT VT =
N->getValueType(0);
14614 SelectionDAG::FlagInserter FlagsInserter(DAG, N0->
getFlags());
14619 if (VT.
isVector() && !LegalOperations &&
14638 if (SVT == MatchingVecType) {
14654 auto IsFreeToExtend = [&](
SDValue V) {
14668 for (SDUse &Use :
V->uses()) {
14670 SDNode *
User =
Use.getUser();
14671 if (
Use.getResNo() != 0 || User == N0.
getNode())
14676 if (
User->getOpcode() != ExtOpcode ||
User->getValueType(0) != VT)
14682 if (IsFreeToExtend(N00) && IsFreeToExtend(N01)) {
14685 return DAG.
getSetCC(
DL, VT, Ext0, Ext1, CC);
14702 SDValue ExtTrueVal = (SetCCWidth == 1)
14706 if (
SDValue SCC = SimplifySelectCC(
DL, N00, N01, ExtTrueVal, Zero, CC,
true))
14718 return DAG.
getSelect(
DL, VT, SetCC, ExtTrueVal, Zero);
14725SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *
N) {
14727 EVT VT =
N->getValueType(0);
14731 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
14777 if (NarrowLoad.getNode() != N0.
getNode()) {
14778 CombineTo(N0.
getNode(), NarrowLoad);
14780 AddToWorklist(oye);
14788 unsigned OpBits =
Op.getScalarValueSizeInBits();
14794 if (OpBits == DestBits) {
14800 if (OpBits < DestBits) {
14809 Flags.setNoSignedWrap(
true);
14817 if (OpBits < DestBits)
14819 else if (OpBits > DestBits)
14839 if (
SDValue ExtLoad = CombineExtLoad(
N))
14874 bool NoReplaceTruncAnd = !N0.
hasOneUse();
14875 bool NoReplaceTrunc =
SDValue(LN00, 0).hasOneUse();
14878 if (NoReplaceTruncAnd) {
14881 CombineTo(N0.
getNode(), TruncAnd);
14883 if (NoReplaceTrunc) {
14888 CombineTo(LN00, Trunc, ExtLoad.
getValue(1));
14907 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
14938 if (NewXor.getNode() == N0.
getNode()) {
14964 "Expected extend op");
15008SDValue DAGCombiner::visitZERO_EXTEND(SDNode *
N) {
15010 EVT VT =
N->getValueType(0);
15014 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
15045 APInt TruncatedBits =
15047 APInt(
Op.getScalarValueSizeInBits(), 0) :
15048 APInt::getBitsSet(
Op.getScalarValueSizeInBits(),
15049 N0.getScalarValueSizeInBits(),
15050 std::min(
Op.getScalarValueSizeInBits(),
15053 SDValue ZExtOrTrunc = DAG.getZExtOrTrunc(Op, DL, VT);
15054 DAG.salvageDebugInfo(*N0.getNode());
15056 return ZExtOrTrunc;
15066 if (NarrowLoad.getNode() != N0.
getNode()) {
15067 CombineTo(N0.
getNode(), NarrowLoad);
15069 AddToWorklist(oye);
15077 if (
N->getFlags().hasNonNeg()) {
15085 if (OpBits == DestBits) {
15091 if (OpBits < DestBits) {
15101 Flags.setNoSignedWrap(
true);
15102 Flags.setNoUnsignedWrap(
true);
15114 AddToWorklist(
Op.getNode());
15118 return ZExtOrTrunc;
15124 AddToWorklist(
Op.getNode());
15160 if (
SDValue ExtLoad = CombineExtLoad(
N))
15180 bool DoXform =
true;
15187 if (isAndLoadExtLoad(AndC, LN00, LoadResultTy, ExtVT))
15203 bool NoReplaceTruncAnd = !N0.
hasOneUse();
15204 bool NoReplaceTrunc =
SDValue(LN00, 0).hasOneUse();
15207 if (NoReplaceTruncAnd) {
15210 CombineTo(N0.
getNode(), TruncAnd);
15212 if (NoReplaceTrunc) {
15217 CombineTo(LN00, Trunc, ExtLoad.
getValue(1));
15226 if (
SDValue ZExtLoad = CombineZExtLogicopShiftLoad(
N))
15239 SelectionDAG::FlagInserter FlagsInserter(DAG, N0->
getFlags());
15242 if (!LegalOperations && VT.
isVector() &&
15274 if (
SDValue SCC = SimplifySelectCC(
15294 if (ShAmtC->getAPIntValue().ugt(KnownZeroBits)) {
15315 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
15337SDValue DAGCombiner::visitANY_EXTEND(SDNode *
N) {
15339 EVT VT =
N->getValueType(0);
15373 if (NarrowLoad.getNode() != N0.
getNode()) {
15374 CombineTo(N0.
getNode(), NarrowLoad);
15376 AddToWorklist(oye);
15410 bool DoXform =
true;
15423 CombineTo(
N, ExtLoad);
15424 if (NoReplaceTrunc) {
15426 recursivelyDeleteUnusedNodes(LN0);
15430 CombineTo(LN0, Trunc, ExtLoad.
getValue(1));
15444 if (!LegalOperations || TLI.
isLoadExtLegal(ExtType, VT, MemVT)) {
15448 CombineTo(
N, ExtLoad);
15450 recursivelyDeleteUnusedNodes(LN0);
15457 SelectionDAG::FlagInserter FlagsInserter(DAG, N0->
getFlags());
15464 if (VT.
isVector() && !LegalOperations) {
15489 if (
SDValue SCC = SimplifySelectCC(
15505SDValue DAGCombiner::visitAssertExt(SDNode *
N) {
15506 unsigned Opcode =
N->getOpcode();
15526 EVT MinAssertVT = AssertVT.
bitsLT(BigA_AssertVT) ? AssertVT : BigA_AssertVT;
15541 if (AssertVT.
bitsLT(BigA_AssertVT)) {
15559 if (AssertVT.
bitsLT(BigA_AssertVT) &&
15579SDValue DAGCombiner::visitAssertAlign(SDNode *
N) {
15589 std::max(AL, AAN->getAlign()));
15600 unsigned AlignShift =
Log2(AL);
15605 if (LHSAlignShift >= AlignShift || RHSAlignShift >= AlignShift) {
15606 if (LHSAlignShift < AlignShift)
15608 if (RHSAlignShift < AlignShift)
15622SDValue DAGCombiner::reduceLoadWidth(SDNode *
N) {
15623 unsigned Opc =
N->getOpcode();
15627 EVT VT =
N->getValueType(0);
15637 unsigned ShAmt = 0;
15642 unsigned ShiftedOffset = 0;
15662 uint64_t MemoryWidth = LN->getMemoryVT().getScalarSizeInBits();
15663 if (MemoryWidth <= ShAmt)
15674 LN->getExtensionType() != ExtType)
15683 unsigned ActiveBits = 0;
15684 if (
Mask.isMask()) {
15685 ActiveBits =
Mask.countr_one();
15686 }
else if (
Mask.isShiftedMask(ShAmt, ActiveBits)) {
15687 ShiftedOffset = ShAmt;
15708 if (!
SRL.hasOneUse())
15721 ShAmt = SRL1C->getZExtValue();
15722 uint64_t MemoryWidth = LN->getMemoryVT().getSizeInBits();
15723 if (ShAmt >= MemoryWidth)
15748 SDNode *
Mask = *(
SRL->user_begin());
15751 unsigned Offset, ActiveBits;
15752 const APInt& ShiftMask =
Mask->getConstantOperandAPInt(1);
15753 if (ShiftMask.
isMask()) {
15775 N0 =
SRL.getOperand(0);
15783 unsigned ShLeftAmt = 0;
15787 ShLeftAmt = N01->getZExtValue();
15800 !isLegalNarrowLdSt(LN0, ExtType, ExtVT, ShAmt))
15803 auto AdjustBigEndianShift = [&](
unsigned ShAmt) {
15804 unsigned LVTStoreBits =
15807 return LVTStoreBits - EVTStoreBits - ShAmt;
15812 unsigned PtrAdjustmentInBits =
15815 uint64_t PtrOff = PtrAdjustmentInBits / 8;
15821 AddToWorklist(NewPtr.
getNode());
15825 const MDNode *OldRanges = LN0->
getRanges();
15826 const MDNode *NewRanges =
nullptr;
15830 if (ShAmt == 0 && OldRanges) {
15838 ConstantRange TruncatedCR = CR.
truncate(BitSize);
15848 NewRanges = OldRanges;
15861 WorklistRemover DeadNodes(*
this);
15866 if (ShLeftAmt != 0) {
15878 if (ShiftedOffset != 0) {
15892SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *
N) {
15895 EVT VT =
N->getValueType(0);
15926 if ((N00Bits <= ExtVTBits ||
15939 if ((N00Bits == ExtVTBits ||
15940 (!IsZext && (N00Bits < ExtVTBits ||
15942 (!LegalOperations ||
15967 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
15975 if (ShAmt->getAPIntValue().ule(VTBits - ExtVTBits)) {
15979 if (((VTBits - ExtVTBits) - ShAmt->getZExtValue()) < InSignBits)
15998 CombineTo(
N, ExtLoad);
16000 AddToWorklist(ExtLoad.
getNode());
16013 CombineTo(
N, ExtLoad);
16022 if (ExtVT == Ld->getMemoryVT() && Ld->hasNUsesOfValue(1, 0) &&
16026 VT,
DL, Ld->getChain(), Ld->getBasePtr(), Ld->getOffset(),
16027 Ld->getMask(), Ld->getPassThru(), ExtVT, Ld->getMemOperand(),
16028 Ld->getAddressingMode(),
ISD::SEXTLOAD, Ld->isExpandingLoad());
16029 CombineTo(
N, Frozen ? N0 : ExtMaskedLoad);
16030 CombineTo(Ld, ExtMaskedLoad, ExtMaskedLoad.
getValue(1));
16037 if (
SDValue(GN0, 0).hasOneUse() && ExtVT == GN0->getMemoryVT() &&
16039 SDValue Ops[] = {GN0->getChain(), GN0->getPassThru(), GN0->getMask(),
16040 GN0->getBasePtr(), GN0->getIndex(), GN0->getScale()};
16043 DAG.
getVTList(VT, MVT::Other), ExtVT,
DL,
Ops, GN0->getMemOperand(),
16046 CombineTo(
N, ExtLoad);
16048 AddToWorklist(ExtLoad.
getNode());
16071 (!LegalOperations ||
16085 bool LegalOperations) {
16086 unsigned InregOpcode =
N->getOpcode();
16090 EVT VT =
N->getValueType(0);
16092 Src.getValueType().getVectorElementType(),
16096 "Expected EXTEND_VECTOR_INREG dag node in input!");
16105 Src = Src.getOperand(0);
16106 if (Src.getValueType() != SrcVT)
16112 return DAG.
getNode(Opcode,
DL, VT, Src);
16115SDValue DAGCombiner::visitEXTEND_VECTOR_INREG(SDNode *
N) {
16117 EVT VT =
N->getValueType(0);
16141SDValue DAGCombiner::visitTRUNCATE_USAT_U(SDNode *
N) {
16142 EVT VT =
N->getValueType(0);
16163 unsigned NumSrcBits = In.getScalarValueSizeInBits();
16165 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
16186 unsigned NumSrcBits = In.getScalarValueSizeInBits();
16188 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
16209 unsigned NumSrcBits = In.getScalarValueSizeInBits();
16211 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
16234 auto AllowedTruncateSat = [&](
unsigned Opc,
EVT SrcVT,
EVT VT) ->
bool {
16246 }
else if (Src.getOpcode() ==
ISD::UMIN) {
16258SDValue DAGCombiner::visitTRUNCATE(SDNode *
N) {
16260 EVT VT =
N->getValueType(0);
16275 return SaturatedTR;
16327 if (LegalTypes && !LegalOperations && VT.
isScalarInteger() && VT != MVT::i1 &&
16329 EVT TrTy =
N->getValueType(0);
16334 if (Src.getOpcode() ==
ISD::SRL && Src.getOperand(0)->hasOneUse()) {
16337 Src = Src.getOperand(0);
16344 EVT VecTy = Src.getOperand(0).getValueType();
16345 EVT ExTy = Src.getValueType();
16349 auto NewEltCnt = EltCnt * SizeRatio;
16354 SDValue EltNo = Src->getOperand(1);
16357 int Index = isLE ? (Elt * SizeRatio + EltOffset)
16358 : (Elt * SizeRatio + (SizeRatio - 1) - EltOffset);
16369 if (!LegalOperations ||
16392 AddToWorklist(Amt.
getNode());
16441 if (BuildVectEltTy == TruncVecEltTy) {
16445 unsigned TruncEltOffset = BuildVecNumElts / TruncVecNumElts;
16446 unsigned FirstElt = isLE ? 0 : (TruncEltOffset - 1);
16448 assert((BuildVecNumElts % TruncVecNumElts) == 0 &&
16449 "Invalid number of elements");
16452 for (
unsigned i = FirstElt, e = BuildVecNumElts; i <
e;
16453 i += TruncEltOffset)
16463 if (
SDValue Reduced = reduceLoadWidth(
N))
16486 unsigned NumDefs = 0;
16490 if (!
X.isUndef()) {
16507 if (NumDefs == 1) {
16508 assert(
V.getNode() &&
"The single defined operand is empty!");
16510 for (
unsigned i = 0, e = VTs.
size(); i != e; ++i) {
16516 AddToWorklist(
NV.getNode());
16531 (!LegalOperations ||
16559 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
16573 if (!LegalOperations && N0.
hasOneUse() &&
16590 Flags.setNoUnsignedWrap(
true);
16615 if (!LegalOperations && N0.
hasOneUse() &&
16656 if (!LegalOperations && N0.
hasOneUse() &&
16664 bool CanFold =
false;
16672 unsigned NeededBits = SrcBits - TruncBits;
16698SDValue DAGCombiner::CombineConsecutiveLoads(SDNode *
N, EVT VT) {
16711 !LD1->hasOneUse() || !LD2->hasOneUse() ||
16712 LD1->getAddressSpace() != LD2->getAddressSpace())
16715 unsigned LD1Fast = 0;
16716 EVT LD1VT = LD1->getValueType(0);
16721 *LD1->getMemOperand(), &LD1Fast) && LD1Fast)
16722 return DAG.
getLoad(VT, SDLoc(
N), LD1->getChain(), LD1->getBasePtr(),
16723 LD1->getPointerInfo(), LD1->getAlign());
16734SDValue DAGCombiner::foldBitcastedFPLogic(SDNode *
N, SelectionDAG &DAG,
16738 EVT VT =
N->getValueType(0);
16775 auto IsBitCastOrFree = [&TLI, FPOpcode](
SDValue Op, EVT VT) {
16789 IsBitCastOrFree(LogicOp0, VT)) {
16792 NumFPLogicOpsConv++;
16801SDValue DAGCombiner::visitBITCAST(SDNode *
N) {
16803 EVT VT =
N->getValueType(0);
16828 if (!LegalOperations ||
16834 if (
C.getNode() !=
N)
16847 auto IsFreeBitcast = [VT](
SDValue V) {
16849 V.getOperand(0).getValueType() == VT) ||
16862 auto CastLoad = [
this, &VT](
SDValue N0,
const SDLoc &
DL) {
16877 if ((LegalOperations || !LN0->
isSimple()) &&
16887 if (
const MDNode *MD = LN0->
getRanges()) {
16899 if (
SDValue NewLd = CastLoad(N0, SDLoc(
N)))
16906 if (
SDValue V = foldBitcastedFPLogic(
N, DAG, TLI))
16926 AddToWorklist(NewConv.
getNode());
16929 if (N0.
getValueType() == MVT::ppcf128 && !LegalTypes) {
16936 AddToWorklist(FlipBit.
getNode());
16943 AddToWorklist(
Hi.getNode());
16945 AddToWorklist(FlipBit.
getNode());
16949 AddToWorklist(FlipBits.
getNode());
16979 AddToWorklist(
X.getNode());
16983 if (OrigXWidth < VTWidth) {
16985 AddToWorklist(
X.getNode());
16986 }
else if (OrigXWidth > VTWidth) {
16991 X.getValueType(),
X,
16993 X.getValueType()));
16994 AddToWorklist(
X.getNode());
16996 AddToWorklist(
X.getNode());
16999 if (N0.
getValueType() == MVT::ppcf128 && !LegalTypes) {
17002 AddToWorklist(Cst.
getNode());
17004 AddToWorklist(
X.getNode());
17006 AddToWorklist(XorResult.
getNode());
17010 SDLoc(XorResult)));
17011 AddToWorklist(XorResult64.
getNode());
17014 DAG.
getConstant(SignBit, SDLoc(XorResult64), MVT::i64));
17015 AddToWorklist(FlipBit.
getNode());
17018 AddToWorklist(FlipBits.
getNode());
17024 AddToWorklist(
X.getNode());
17029 AddToWorklist(Cst.
getNode());
17037 if (
SDValue CombineLD = CombineConsecutiveLoads(N0.
getNode(), VT))
17060 auto PeekThroughBitcast = [&](
SDValue Op) {
17062 Op.getOperand(0).getValueType() == VT)
17079 SmallVector<int, 8> NewMask;
17081 for (
int i = 0; i != MaskScale; ++i)
17082 NewMask.
push_back(M < 0 ? -1 : M * MaskScale + i);
17087 return LegalShuffle;
17093SDValue DAGCombiner::visitBUILD_PAIR(SDNode *
N) {
17094 EVT VT =
N->getValueType(0);
17095 return CombineConsecutiveLoads(
N, VT);
17098SDValue DAGCombiner::visitFREEZE(SDNode *
N) {
17112 assert(
N->getOperand(0) == FrozenN0 &&
"Expected cycle in DAG");
17140 bool AllowMultipleMaybePoisonOperands =
17168 SmallSet<SDValue, 8> MaybePoisonOperands;
17169 SmallVector<unsigned, 8> MaybePoisonOperandNumbers;
17173 bool HadMaybePoisonOperands = !MaybePoisonOperands.
empty();
17174 bool IsNewMaybePoisonOperand = MaybePoisonOperands.
insert(
Op).second;
17175 if (IsNewMaybePoisonOperand)
17176 MaybePoisonOperandNumbers.
push_back(OpNo);
17177 if (!HadMaybePoisonOperands)
17179 if (IsNewMaybePoisonOperand && !AllowMultipleMaybePoisonOperands) {
17188 for (
unsigned OpNo : MaybePoisonOperandNumbers) {
17199 SDValue MaybePoisonOperand =
N->getOperand(0).getOperand(OpNo);
17201 if (MaybePoisonOperand.
isUndef())
17208 FrozenMaybePoisonOperand.
getOperand(0) == FrozenMaybePoisonOperand) {
17212 MaybePoisonOperand);
17248 SDNodeFlags SrcFlags = N0->
getFlags();
17249 SDNodeFlags SafeFlags;
17263 N->getFlags().hasAllowContract();
17267template <
class MatchContextClass>
17268SDValue DAGCombiner::visitFADDForFMACombine(SDNode *
N) {
17271 EVT VT =
N->getValueType(0);
17273 MatchContextClass matcher(DAG, TLI,
N);
17276 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
17281 bool HasFMAD = !UseVP && (LegalOperations && TLI.
isFMADLegal(DAG,
N));
17285 (!LegalOperations || matcher.isOperationLegalOrCustom(
ISD::FMA, VT)) &&
17289 if (!HasFMAD && !HasFMA)
17292 bool AllowFusionGlobally =
17295 if (!AllowFusionGlobally && !
N->getFlags().hasAllowContract())
17321 return AllowFusionGlobally ||
N->getFlags().hasAllowContract();
17332 return matcher.getNode(PreferredFusedOpcode, SL, VT, N0.
getOperand(0),
17339 return matcher.getNode(PreferredFusedOpcode, SL, VT, N1.
getOperand(0),
17351 bool CanReassociate =
N->getFlags().hasAllowReassociation();
17352 if (CanReassociate) {
17357 }
else if (isFusedOp(N1) && N1.
hasOneUse()) {
17363 while (
E && isFusedOp(TmpFMA) && TmpFMA.
hasOneUse()) {
17368 SDValue CDE = matcher.getNode(PreferredFusedOpcode, SL, VT,
C,
D,
E);
17387 return matcher.getNode(
17388 PreferredFusedOpcode, SL, VT,
17401 return matcher.getNode(
17402 PreferredFusedOpcode, SL, VT,
17414 return matcher.getNode(
17415 PreferredFusedOpcode, SL, VT,
X,
Y,
17416 matcher.getNode(PreferredFusedOpcode, SL, VT,
17420 if (isFusedOp(N0)) {
17441 return matcher.getNode(
17442 PreferredFusedOpcode, SL, VT,
17445 matcher.getNode(PreferredFusedOpcode, SL, VT,
17451 if (isFusedOp(N00)) {
17465 if (isFusedOp(N1)) {
17486 if (isFusedOp(N10)) {
17503template <
class MatchContextClass>
17504SDValue DAGCombiner::visitFSUBForFMACombine(SDNode *
N) {
17507 EVT VT =
N->getValueType(0);
17509 MatchContextClass matcher(DAG, TLI,
N);
17512 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
17517 bool HasFMAD = !UseVP && (LegalOperations && TLI.
isFMADLegal(DAG,
N));
17521 (!LegalOperations || matcher.isOperationLegalOrCustom(
ISD::FMA, VT)) &&
17525 if (!HasFMAD && !HasFMA)
17528 const SDNodeFlags
Flags =
N->getFlags();
17529 bool AllowFusionGlobally =
17533 if (!AllowFusionGlobally && !
N->getFlags().hasAllowContract())
17542 bool NoSignedZero =
Flags.hasNoSignedZeros();
17549 return AllowFusionGlobally ||
N->getFlags().hasAllowContract();
17555 return matcher.getNode(PreferredFusedOpcode, SL, VT, XY.
getOperand(0),
17566 return matcher.getNode(
17567 PreferredFusedOpcode, SL, VT,
17568 matcher.getNode(
ISD::FNEG, SL, VT, YZ.getOperand(0)),
17569 YZ.getOperand(1),
X);
17579 if (
SDValue V = tryToFoldXSubYZ(N0, N1))
17582 if (
SDValue V = tryToFoldXYSubZ(N0, N1))
17586 if (
SDValue V = tryToFoldXYSubZ(N0, N1))
17589 if (
SDValue V = tryToFoldXSubYZ(N0, N1))
17598 return matcher.
getNode(PreferredFusedOpcode, SL, VT,
17599 matcher.getNode(
ISD::FNEG, SL, VT, N00), N01,
17600 matcher.getNode(
ISD::FNEG, SL, VT, N1));
17612 return matcher.getNode(
17613 PreferredFusedOpcode, SL, VT,
17616 matcher.getNode(
ISD::FNEG, SL, VT, N1));
17628 return matcher.getNode(
17629 PreferredFusedOpcode, SL, VT,
17650 return matcher.getNode(
17653 PreferredFusedOpcode, SL, VT,
17674 return matcher.getNode(
17677 PreferredFusedOpcode, SL, VT,
17694 if (
Aggressive &&
N->getFlags().hasAllowReassociation()) {
17695 bool CanFuse =
N->getFlags().hasAllowContract();
17698 if (CanFuse && isFusedOp(N0) &&
17699 isContractableAndReassociableFMUL(N0.
getOperand(2)) &&
17701 return matcher.getNode(
17703 matcher.
getNode(PreferredFusedOpcode, SL, VT,
17711 if (CanFuse && isFusedOp(N1) &&
17712 isContractableAndReassociableFMUL(N1.
getOperand(2)) &&
17717 PreferredFusedOpcode, SL, VT,
17720 matcher.
getNode(PreferredFusedOpcode, SL, VT,
17721 matcher.getNode(
ISD::FNEG, SL, VT, N20), N21, N0));
17726 if (isFusedOp(N0) && N0->
hasOneUse()) {
17730 if (isContractableAndReassociableFMUL(N020) &&
17733 return matcher.getNode(
17736 PreferredFusedOpcode, SL, VT,
17739 matcher.getNode(
ISD::FNEG, SL, VT, N1)));
17752 if (isFusedOp(N00)) {
17754 if (isContractableAndReassociableFMUL(N002) &&
17757 return matcher.getNode(
17758 PreferredFusedOpcode, SL, VT,
17762 PreferredFusedOpcode, SL, VT,
17765 matcher.getNode(
ISD::FNEG, SL, VT, N1)));
17775 if (isContractableAndReassociableFMUL(N120) &&
17781 PreferredFusedOpcode, SL, VT,
17785 PreferredFusedOpcode, SL, VT,
17803 if (isContractableAndReassociableFMUL(N102) &&
17809 PreferredFusedOpcode, SL, VT,
17814 PreferredFusedOpcode, SL, VT,
17828SDValue DAGCombiner::visitFMULForFMADistributiveCombine(SDNode *
N) {
17831 EVT VT =
N->getValueType(0);
17841 if (!
FAdd->getFlags().hasNoInfs())
17852 bool HasFMAD = LegalOperations && TLI.
isFMADLegal(DAG,
N);
17855 if (!HasFMAD && !HasFMA)
17867 if (
C->isExactlyValue(+1.0))
17868 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
17870 if (
C->isExactlyValue(-1.0))
17871 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
17878 if (
SDValue FMA = FuseFADD(N0, N1))
17880 if (
SDValue FMA = FuseFADD(N1, N0))
17890 if (C0->isExactlyValue(+1.0))
17891 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
17894 if (C0->isExactlyValue(-1.0))
17895 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
17900 if (C1->isExactlyValue(+1.0))
17901 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
17903 if (C1->isExactlyValue(-1.0))
17904 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
17911 if (
SDValue FMA = FuseFSUB(N0, N1))
17913 if (
SDValue FMA = FuseFSUB(N1, N0))
17919SDValue DAGCombiner::visitVP_FADD(SDNode *
N) {
17920 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
17923 if (
SDValue Fused = visitFADDForFMACombine<VPMatchContext>(
N)) {
17925 AddToWorklist(Fused.getNode());
17931SDValue DAGCombiner::visitFADD(SDNode *
N) {
17936 EVT VT =
N->getValueType(0);
17938 SDNodeFlags
Flags =
N->getFlags();
17939 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
17949 if (N0CFP && !N1CFP)
17954 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
17959 if (N1C && N1C->
isZero())
17964 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17970 N1, DAG, LegalOperations, ForCodeSize))
17976 N0, DAG, LegalOperations, ForCodeSize))
17983 return C &&
C->isExactlyValue(-2.0);
17987 if (isFMulNegTwo(N0)) {
17993 if (isFMulNegTwo(N1)) {
18004 if (
Flags.hasNoNaNs() && AllowNewConst) {
18017 if (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros() &&
18035 if (CFP01 && !CFP00 && N0.
getOperand(0) == N1) {
18056 if (CFP11 && !CFP10 && N1.
getOperand(0) == N0) {
18103 if (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros()) {
18106 VT, N0, N1, Flags))
18111 if (
SDValue Fused = visitFADDForFMACombine<EmptyMatchContext>(
N)) {
18113 AddToWorklist(Fused.getNode());
18119SDValue DAGCombiner::visitSTRICT_FADD(SDNode *
N) {
18123 EVT VT =
N->getValueType(0);
18124 EVT ChainVT =
N->getValueType(1);
18126 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18131 N1, DAG, LegalOperations, ForCodeSize)) {
18133 {Chain, N0, NegN1});
18139 N0, DAG, LegalOperations, ForCodeSize)) {
18141 {Chain, N1, NegN0});
18146SDValue DAGCombiner::visitFSUB(SDNode *
N) {
18151 EVT VT =
N->getValueType(0);
18153 const SDNodeFlags
Flags =
N->getFlags();
18154 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18165 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
18168 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
18172 if (N1CFP && N1CFP->
isZero()) {
18181 if (
Flags.hasNoNaNs())
18186 if (N0CFP && N0CFP->
isZero()) {
18204 if (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros() &&
18220 if (
SDValue Fused = visitFSUBForFMACombine<EmptyMatchContext>(
N)) {
18221 AddToWorklist(Fused.getNode());
18243SDValue DAGCombiner::combineFMulOrFDivWithIntPow2(SDNode *
N) {
18244 EVT VT =
N->getValueType(0);
18250 std::optional<int> Mantissa;
18251 auto GetConstAndPow2Ops = [&](
unsigned ConstOpIdx) {
18252 if (ConstOpIdx == 1 &&
N->getOpcode() ==
ISD::FDIV)
18268 auto IsFPConstValid = [
N, MaxExpChange, &Mantissa](ConstantFPSDNode *CFP) {
18269 if (CFP ==
nullptr)
18272 const APFloat &APF = CFP->getValueAPF();
18280 int CurExp =
ilogb(APF);
18283 N->getOpcode() ==
ISD::FMUL ? CurExp : (CurExp - MaxExpChange);
18286 N->getOpcode() ==
ISD::FDIV ? CurExp : (CurExp + MaxExpChange);
18294 Mantissa = ThisMantissa;
18296 return *Mantissa == ThisMantissa && ThisMantissa > 0;
18303 if (!GetConstAndPow2Ops(0) && !GetConstAndPow2Ops(1))
18332 NewIntVT, DAG.
getBitcast(NewIntVT, ConstOp), Shift);
18337SDValue DAGCombiner::visitFMUL(SDNode *
N) {
18341 EVT VT =
N->getValueType(0);
18343 const SDNodeFlags
Flags =
N->getFlags();
18344 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18360 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
18363 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
18366 if (
Flags.hasAllowReassociation()) {
18392 VT, N0, N1, Flags))
18416 HandleSDNode NegN0Handle(NegN0);
18426 if (
Flags.hasNoNaNs() &&
Flags.hasNoSignedZeros() &&
18437 if (TrueOpnd && FalseOpnd &&
18458 if (TrueOpnd->isExactlyValue(-1.0) && FalseOpnd->isExactlyValue(1.0) &&
18462 if (TrueOpnd->isExactlyValue(1.0) && FalseOpnd->isExactlyValue(-1.0))
18471 if (
SDValue Fused = visitFMULForFMADistributiveCombine(
N)) {
18472 AddToWorklist(Fused.getNode());
18478 if (
SDValue R = combineFMulOrFDivWithIntPow2(
N))
18484template <
class MatchContextClass>
SDValue DAGCombiner::visitFMA(SDNode *
N) {
18491 EVT VT =
N->getValueType(0);
18494 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18495 MatchContextClass matcher(DAG, TLI,
N);
18510 HandleSDNode NegN0Handle(NegN0);
18518 if (
N->getFlags().hasNoNaNs() &&
N->getFlags().hasNoInfs()) {
18519 if (
N->getFlags().hasNoSignedZeros() ||
18521 if (N0CFP && N0CFP->
isZero())
18523 if (N1CFP && N1CFP->
isZero())
18532 return matcher.getNode(
ISD::FADD,
DL, VT, N0, N2);
18537 return matcher.getNode(
ISD::FMA,
DL, VT, N1, N0, N2);
18539 bool CanReassociate =
N->getFlags().hasAllowReassociation();
18540 if (CanReassociate) {
18545 return matcher.getNode(
18554 return matcher.getNode(
18564 return matcher.getNode(
ISD::FADD,
DL, VT, N0, N2);
18569 AddToWorklist(RHSNeg.
getNode());
18570 return matcher.getNode(
ISD::FADD,
DL, VT, N2, RHSNeg);
18584 if (CanReassociate) {
18586 if (N1CFP && N0 == N2) {
18604 SDValue(
N, 0), DAG, LegalOperations, ForCodeSize))
18609SDValue DAGCombiner::visitFMAD(SDNode *
N) {
18613 EVT VT =
N->getValueType(0);
18623SDValue DAGCombiner::visitFMULADD(SDNode *
N) {
18627 EVT VT =
N->getValueType(0);
18645SDValue DAGCombiner::combineRepeatedFPDivisors(SDNode *
N) {
18649 const SDNodeFlags
Flags =
N->getFlags();
18650 if (LegalDAG || !
Flags.hasAllowReciprocal())
18665 unsigned NumElts = 1;
18666 EVT VT =
N->getValueType(0);
18670 if (!MinUses || (N1->
use_size() * NumElts) < MinUses)
18675 SetVector<SDNode *>
Users;
18676 for (
auto *U : N1->
users()) {
18677 if (
U->getOpcode() ==
ISD::FDIV &&
U->getOperand(1) == N1) {
18679 if (
U->getOperand(1).getOpcode() ==
ISD::FSQRT &&
18680 U->getOperand(0) ==
U->getOperand(1).getOperand(0) &&
18681 U->getFlags().hasAllowReassociation() &&
18682 U->getFlags().hasNoSignedZeros())
18687 if (
U->getFlags().hasAllowReciprocal())
18694 if ((
Users.size() * NumElts) < MinUses)
18702 for (
auto *U :
Users) {
18703 SDValue Dividend =
U->getOperand(0);
18704 if (Dividend != FPOne) {
18706 Reciprocal, Flags);
18707 CombineTo(U, NewNode);
18708 }
else if (U != Reciprocal.
getNode()) {
18711 CombineTo(U, Reciprocal);
18717SDValue DAGCombiner::visitFDIV(SDNode *
N) {
18720 EVT VT =
N->getValueType(0);
18722 SDNodeFlags
Flags =
N->getFlags();
18723 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18734 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
18737 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
18754 (!LegalOperations ||
18764 if (
Flags.hasAllowReciprocal()) {
18773 N1AllowReciprocal) {
18804 A =
Y.getOperand(0);
18813 if (
SDValue Rsqrt = buildRsqrtEstimate(AAZ))
18817 recursivelyDeleteUnusedNodes(AAZ.
getNode());
18825 AddToWorklist(Div.
getNode());
18832 if (
Flags.hasNoInfs())
18833 if (
SDValue RV = BuildDivEstimate(N0, N1, Flags))
18839 Flags.hasAllowReassociation())
18851 HandleSDNode NegN0Handle(NegN0);
18859 if (
SDValue R = combineFMulOrFDivWithIntPow2(
N))
18865SDValue DAGCombiner::visitFREM(SDNode *
N) {
18868 EVT VT =
N->getValueType(0);
18869 SDNodeFlags
Flags =
N->getFlags();
18870 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18880 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
18890 bool NeedsCopySign = !
Flags.hasNoSignedZeros() &&
18909SDValue DAGCombiner::visitFSQRT(SDNode *
N) {
18910 SDNodeFlags
Flags =
N->getFlags();
18914 if (!
Flags.hasApproximateFuncs() || !
Flags.hasNoInfs())
18922 SelectionDAG::FlagInserter FlagInserter(DAG, Flags);
18927 return buildSqrtEstimate(N0);
18942 if (YTy == MVT::f128)
18959SDValue DAGCombiner::visitFCOPYSIGN(SDNode *
N) {
18962 EVT VT =
N->getValueType(0);
19000SDValue DAGCombiner::visitFPOW(SDNode *
N) {
19004 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
19010 EVT VT =
N->getValueType(0);
19019 SDNodeFlags
Flags =
N->getFlags();
19020 if (!
Flags.hasNoSignedZeros() || !
Flags.hasNoInfs() || !
Flags.hasNoNaNs() ||
19021 !
Flags.hasApproximateFuncs())
19040 if (ExponentIs025 || ExponentIs075) {
19048 SDNodeFlags
Flags =
N->getFlags();
19051 if ((!
Flags.hasNoSignedZeros() && ExponentIs025) || !
Flags.hasNoInfs() ||
19052 !
Flags.hasApproximateFuncs())
19089 EVT VT =
N->getValueType(0);
19095 assert(IsSigned || IsUnsigned);
19100 if (IsSigned && !IsSignedZeroSafe)
19104 if (IsUnsigned && !IsSignedZeroSafe && !TLI.
isFAbsFree(VT))
19112 constexpr unsigned MaxClamps = 2;
19116 SDValue IntVal =
N->getOperand(0);
19117 for (
unsigned Level = 0; Level < MaxClamps; ++Level) {
19118 if (!IntVal.hasOneUse() ||
19119 (IntVal.getOpcode() != MinOp && IntVal.getOpcode() != MaxOp))
19124 IntConst = IntConstNode->getAPIntValue();
19134 !IsExact ||
static_cast<const APInt &
>(RoundTrip) != IntConst)
19136 bool IsMin = IntVal.getOpcode() == MinOp;
19138 IntVal = IntVal.getOperand(0);
19143 if (IntVal.getOpcode() != FPToIntOp ||
19144 IntVal.getOperand(0).getValueType() != VT)
19147 SDValue Result = IntVal.getOperand(0);
19148 if (IsUnsigned && !IsSignedZeroSafe && TLI.
isFAbsFree(VT))
19152 for (
const ClampInfo &Clamp :
reverse(Clamps)) {
19153 unsigned FPClampOp =
19157 Result = DAG.
getNode(FPClampOp,
DL, VT, Result, Clamp.Constant);
19162SDValue DAGCombiner::visitSINT_TO_FP(SDNode *
N) {
19164 EVT VT =
N->getValueType(0);
19216SDValue DAGCombiner::visitUINT_TO_FP(SDNode *
N) {
19218 EVT VT =
N->getValueType(0);
19262 EVT VT =
N->getValueType(0);
19268 EVT SrcVT = Src.getValueType();
19283 unsigned ActualSize = std::min(InputSize, OutputSize);
19292 return DAG.
getNode(ExtOp,
DL, VT, Src);
19301SDValue DAGCombiner::visitFP_TO_SINT(SDNode *
N) {
19303 EVT VT =
N->getValueType(0);
19317SDValue DAGCombiner::visitFP_TO_UINT(SDNode *
N) {
19319 EVT VT =
N->getValueType(0);
19333SDValue DAGCombiner::visitXROUND(SDNode *
N) {
19335 EVT VT =
N->getValueType(0);
19351SDValue DAGCombiner::visitFP_ROUND(SDNode *
N) {
19354 EVT VT =
N->getValueType(0);
19367 const bool NIsTrunc =
N->getConstantOperandVal(1) == 1;
19389 if ((
N->getFlags().hasAllowContract() &&
19407 AddToWorklist(Tmp.
getNode());
19411 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
19421 EVT VT =
N->getValueType(0);
19423 unsigned NarrowingOp;
19424 switch (
N->getOpcode()) {
19454SDValue DAGCombiner::visitFP_EXTEND(SDNode *
N) {
19455 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
19457 EVT VT =
N->getValueType(0);
19461 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
19481 if (
In.getValueType() == VT)
return In;
19495 CombineTo(
N, ExtLoad);
19504 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
19508 return CastEliminated;
19513SDValue DAGCombiner::visitFCEIL(SDNode *
N) {
19515 EVT VT =
N->getValueType(0);
19524SDValue DAGCombiner::visitFTRUNC(SDNode *
N) {
19526 EVT VT =
N->getValueType(0);
19549SDValue DAGCombiner::visitFFREXP(SDNode *
N) {
19558SDValue DAGCombiner::visitFFLOOR(SDNode *
N) {
19560 EVT VT =
N->getValueType(0);
19569SDValue DAGCombiner::visitFNEG(SDNode *
N) {
19571 EVT VT =
N->getValueType(0);
19572 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
19595 if (
SDValue Cast = foldSignChangeInBitcast(
N))
19601SDValue DAGCombiner::visitFMinMax(SDNode *
N) {
19604 EVT VT =
N->getValueType(0);
19605 const SDNodeFlags
Flags =
N->getFlags();
19606 unsigned Opc =
N->getOpcode();
19608 bool ReturnsOtherForAllNaNs =
19612 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
19621 return DAG.
getNode(
N->getOpcode(), SDLoc(
N), VT, N1, N0);
19633 if (PropAllNaNsToQNaNs) {
19637 }
else if (ReturnsOtherForAllNaNs || !AF.
isSignaling()) {
19638 return N->getOperand(0);
19651 (ReturnsOtherForAllNaNs ||
Flags.hasNoNaNs()))
19652 return N->getOperand(1);
19660 if (IsMin != AF.
isNegative() && (PropAllNaNsToQNaNs ||
Flags.hasNoNaNs()))
19661 return N->getOperand(0);
19669 if (
SDValue SD = reassociateReduction(
19673 Opc, SDLoc(
N), VT, N0, N1, Flags))
19679SDValue DAGCombiner::visitFABS(SDNode *
N) {
19681 EVT VT =
N->getValueType(0);
19691 if (
SDValue Cast = foldSignChangeInBitcast(
N))
19697SDValue DAGCombiner::visitBRCOND(SDNode *
N) {
19724 bool Updated =
false;
19736 return True || False;
19740 if (!IsAlwaysTrueOrFalse(
Cond, S1C)) {
19747 S1 =
S1->getOperand(0);
19778 HandleSDNode ChainHandle(Chain);
19779 if (
SDValue NewN1 = rebuildSetCC(N1))
19781 ChainHandle.getValue(), NewN1, N2,
N->getFlags());
19790 (
N.getOperand(0).hasOneUse() &&
19791 N.getOperand(0).getOpcode() ==
ISD::SRL))) {
19794 N =
N.getOperand(0);
19841 HandleSDNode XORHandle(
N);
19843 SDValue Tmp = visitXOR(
N.getNode());
19850 N = XORHandle.getValue();
19862 bool Equal =
false;
19872 EVT SetCCVT =
N.getValueType();
19881 return DAG.
getSetCC(SDLoc(
N), SetCCVT, Op0, Op1, CC);
19890SDValue DAGCombiner::visitBR_CC(SDNode *
N) {
19902 CondLHS, CondRHS, CC->
get(), SDLoc(
N),
19917 bool &IsLoad,
bool &IsMasked,
SDValue &Ptr,
19920 if (LD->isIndexed())
19922 EVT VT = LD->getMemoryVT();
19925 Ptr = LD->getBasePtr();
19927 if (ST->isIndexed())
19929 EVT VT = ST->getMemoryVT();
19932 Ptr = ST->getBasePtr();
19935 if (LD->isIndexed())
19937 EVT VT = LD->getMemoryVT();
19941 Ptr = LD->getBasePtr();
19944 if (ST->isIndexed())
19946 EVT VT = ST->getMemoryVT();
19950 Ptr = ST->getBasePtr();
19964bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *
N) {
19968 bool IsLoad =
true;
19969 bool IsMasked =
false;
19991 bool Swapped =
false;
20020 if (Val == BasePtr)
20029 SmallPtrSet<const SDNode *, 32> Visited;
20039 for (SDUse &Use :
BasePtr->uses()) {
20042 if (
Use.getUser() == Ptr.
getNode() || Use != BasePtr)
20055 SDValue Op1 =
Use.getUser()->getOperand((
Use.getOperandNo() + 1) & 1);
20074 bool RealUse =
false;
20076 for (SDNode *User : Ptr->
users()) {
20110 WorklistRemover DeadNodes(*
this);
20119 deleteAndRecombine(
N);
20125 for (SDNode *OtherUse : OtherUses) {
20126 unsigned OffsetIdx = 1;
20127 if (OtherUse->getOperand(OffsetIdx).getNode() ==
BasePtr.getNode())
20129 assert(OtherUse->getOperand(!OffsetIdx).getNode() ==
BasePtr.getNode() &&
20130 "Expected BasePtr operand");
20144 const APInt &Offset0 = CN->getAPIntValue();
20145 const APInt &Offset1 =
Offset->getAsAPIntVal();
20146 int X0 = (OtherUse->getOpcode() ==
ISD::SUB && OffsetIdx == 1) ? -1 : 1;
20147 int Y0 = (OtherUse->getOpcode() ==
ISD::SUB && OffsetIdx == 0) ? -1 : 1;
20151 unsigned Opcode = (Y0 * Y1 < 0) ?
ISD::SUB : ISD::
ADD;
20153 APInt CNV = Offset0;
20154 if (X0 < 0) CNV = -CNV;
20155 if (X1 * Y0 * Y1 < 0) CNV = CNV + Offset1;
20156 else CNV = CNV - Offset1;
20158 SDLoc
DL(OtherUse);
20165 DAG.
getNode(Opcode,
DL, OtherUse->getValueType(0), NewOp1, NewOp2);
20167 deleteAndRecombine(OtherUse);
20172 deleteAndRecombine(Ptr.
getNode());
20173 AddToWorklist(
Result.getNode());
20205 bool IsLoad =
true;
20206 bool IsMasked =
false;
20209 IsMasked, OtherPtr, TLI)) {
20229 bool &IsMasked,
SDValue &Ptr,
20235 IsMasked, Ptr, TLI) ||
20247 if (U.getResNo() != Ptr.
getResNo())
20273bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *
N) {
20277 bool IsLoad =
true;
20278 bool IsMasked =
false;
20299 ++PostIndexedNodes;
20303 WorklistRemover DeadNodes(*
this);
20312 deleteAndRecombine(
N);
20316 Result.getValue(IsLoad ? 1 : 0));
20317 deleteAndRecombine(
Op);
20322SDValue DAGCombiner::SplitIndexingFromLoad(LoadSDNode *LD) {
20333 "Cannot split out indexing using opaque target constants");
20349bool DAGCombiner::getTruncatedStoreValue(StoreSDNode *ST,
SDValue &Val) {
20351 EVT STMemType =
ST->getMemoryVT();
20352 if (STType == STMemType)
20373bool DAGCombiner::extendLoadedValueToExtension(LoadSDNode *LD,
SDValue &Val) {
20374 EVT LDMemType =
LD->getMemoryVT();
20375 EVT LDType =
LD->getValueType(0);
20377 "Attempting to extend value of non-matching type");
20378 if (LDType == LDMemType)
20381 switch (
LD->getExtensionType()) {
20399StoreSDNode *DAGCombiner::getUniqueStoreFeeding(LoadSDNode *LD,
20407 StoreSDNode *
ST =
nullptr;
20417 if (!BasePtrST.equalBaseIndex(BasePtrLD, DAG,
Offset))
20420 GatherAllAliases(Store, Chain, Aliases);
20421 if (Aliases.
empty() ||
20422 (Aliases.
size() == 1 && Aliases.
front().getNode() == Store))
20431 if (BasePtrST.equalBaseIndex(BasePtrLD, DAG,
Offset))
20439SDValue DAGCombiner::ForwardStoreValueToDirectLoad(LoadSDNode *LD) {
20445 StoreSDNode *
ST = getUniqueStoreFeeding(LD,
Offset);
20447 if (!ST || !
ST->isSimple() ||
ST->getAddressSpace() !=
LD->getAddressSpace())
20450 EVT LDType =
LD->getValueType(0);
20451 EVT LDMemType =
LD->getMemoryVT();
20452 EVT STMemType =
ST->getMemoryVT();
20453 EVT STType =
ST->getValue().getValueType();
20477 int64_t OrigOffset =
Offset;
20490 STCoversLD = (
Offset == 0) && LdMemSize == StMemSize;
20496 if (
LD->isIndexed()) {
20501 SDValue Idx = SplitIndexingFromLoad(LD);
20503 return CombineTo(LD,
Ops, 3);
20505 return CombineTo(LD, Val, Chain);
20512 if (
Offset == 0 && LDType == STType && STMemType == LDMemType) {
20515 return ReplaceLd(LD,
ST->getValue(), Chain);
20523 SDLoc(ST), STType);
20525 return ReplaceLd(LD, Val, Chain);
20543 if (
LD->getBasePtr().isUndef() ||
Offset != 0)
20548 if (!getTruncatedStoreValue(ST, Val))
20552 if (STMemType != LDMemType) {
20560 if (!extendLoadedValueToExtension(LD, Val))
20562 return ReplaceLd(LD, Val, Chain);
20567 deleteAndRecombine(Val.
getNode());
20571SDValue DAGCombiner::visitLOAD(SDNode *
N) {
20580 if (
LD->isSimple()) {
20581 if (
N->getValueType(1) == MVT::Other) {
20583 if (!
N->hasAnyUseOfValue(0)) {
20591 dbgs() <<
"\nWith chain: "; Chain.
dump(&DAG);
20593 WorklistRemover DeadNodes(*
this);
20595 AddUsersToWorklist(Chain.
getNode());
20596 if (
N->use_empty())
20597 deleteAndRecombine(
N);
20603 assert(
N->getValueType(2) == MVT::Other &&
"Malformed indexed loads?");
20611 if (!
N->hasAnyUseOfValue(0) && (CanSplitIdx || !
N->hasAnyUseOfValue(1))) {
20614 if (
N->hasAnyUseOfValue(1) && CanSplitIdx) {
20615 Index = SplitIndexingFromLoad(LD);
20618 AddUsersToWorklist(
N);
20622 dbgs() <<
"\nWith: ";
Undef.dump(&DAG);
20623 dbgs() <<
" and 2 other values\n");
20624 WorklistRemover DeadNodes(*
this);
20628 deleteAndRecombine(
N);
20636 if (
auto V = ForwardStoreValueToDirectLoad(LD))
20643 if (*Alignment >
LD->getAlign() &&
20644 isAligned(*Alignment,
LD->getSrcValueOffset())) {
20646 LD->getExtensionType(), SDLoc(
N),
LD->getValueType(0), Chain, Ptr,
20647 LD->getPointerInfo(),
LD->getMemoryVT(), *Alignment,
20648 LD->getMemOperand()->getFlags(),
LD->getAAInfo());
20656 if (
LD->isUnindexed()) {
20658 SDValue BetterChain = FindBetterChain(LD, Chain);
20661 if (Chain != BetterChain) {
20666 ReplLoad = DAG.
getLoad(
N->getValueType(0), SDLoc(LD),
20667 BetterChain, Ptr,
LD->getMemOperand());
20669 ReplLoad = DAG.
getExtLoad(
LD->getExtensionType(), SDLoc(LD),
20670 LD->getValueType(0),
20671 BetterChain, Ptr,
LD->getMemoryVT(),
20672 LD->getMemOperand());
20677 MVT::Other, Chain, ReplLoad.
getValue(1));
20680 return CombineTo(
N, ReplLoad.
getValue(0), Token);
20685 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
20690 if (SliceUpLoad(
N))
20710struct LoadedSlice {
20714 bool ForCodeSize =
false;
20717 unsigned Loads = 0;
20718 unsigned Truncates = 0;
20719 unsigned CrossRegisterBanksCopies = 0;
20720 unsigned ZExts = 0;
20721 unsigned Shift = 0;
20723 explicit Cost(
bool ForCodeSize) : ForCodeSize(ForCodeSize) {}
20726 Cost(
const LoadedSlice &LS,
bool ForCodeSize)
20727 : ForCodeSize(ForCodeSize), Loads(1) {
20728 EVT TruncType =
LS.Inst->getValueType(0);
20729 EVT LoadedType =
LS.getLoadedType();
20730 if (TruncType != LoadedType &&
20731 !
LS.DAG->getTargetLoweringInfo().isZExtFree(LoadedType, TruncType))
20739 void addSliceGain(
const LoadedSlice &LS) {
20741 const TargetLowering &TLI =
LS.DAG->getTargetLoweringInfo();
20748 if (
LS.canMergeExpensiveCrossRegisterBankCopy())
20749 ++CrossRegisterBanksCopies;
20753 Loads +=
RHS.Loads;
20754 Truncates +=
RHS.Truncates;
20755 CrossRegisterBanksCopies +=
RHS.CrossRegisterBanksCopies;
20756 ZExts +=
RHS.ZExts;
20757 Shift +=
RHS.Shift;
20762 return Loads ==
RHS.Loads && Truncates ==
RHS.Truncates &&
20763 CrossRegisterBanksCopies ==
RHS.CrossRegisterBanksCopies &&
20764 ZExts ==
RHS.ZExts && Shift ==
RHS.Shift;
20772 unsigned ExpensiveOpsLHS = Loads + CrossRegisterBanksCopies;
20773 unsigned ExpensiveOpsRHS =
RHS.Loads +
RHS.CrossRegisterBanksCopies;
20776 if (!ForCodeSize && ExpensiveOpsLHS != ExpensiveOpsRHS)
20777 return ExpensiveOpsLHS < ExpensiveOpsRHS;
20778 return (Truncates + ZExts + Shift + ExpensiveOpsLHS) <
20779 (
RHS.Truncates +
RHS.ZExts +
RHS.Shift + ExpensiveOpsRHS);
20794 LoadSDNode *Origin;
20803 LoadedSlice(SDNode *Inst =
nullptr, LoadSDNode *Origin =
nullptr,
20804 unsigned Shift = 0, SelectionDAG *DAG =
nullptr)
20805 : Inst(Inst), Origin(Origin), Shift(Shift), DAG(DAG) {}
20810 APInt getUsedBits()
const {
20815 assert(Origin &&
"No original load to compare against.");
20817 assert(Inst &&
"This slice is not bound to an instruction");
20819 "Extracted slice is bigger than the whole type!");
20821 UsedBits.setAllBits();
20822 UsedBits = UsedBits.zext(
BitWidth);
20823 UsedBits <<= Shift;
20828 unsigned getLoadedSize()
const {
20829 unsigned SliceSize = getUsedBits().popcount();
20830 assert(!(SliceSize & 0x7) &&
"Size is not a multiple of a byte.");
20831 return SliceSize / 8;
20836 EVT getLoadedType()
const {
20837 assert(DAG &&
"Missing context");
20845 uint64_t
Offset = getOffsetFromBase();
20852 bool isLegal()
const {
20854 if (!Origin || !Inst || !DAG)
20864 EVT SliceType = getLoadedType();
20875 if (PtrType == MVT::Untyped || PtrType.
isExtended())
20888 if (TruncateType != SliceType &&
20898 uint64_t getOffsetFromBase()
const {
20899 assert(DAG &&
"Missing context.");
20901 assert(!(Shift & 0x7) &&
"Shifts not aligned on Bytes are not supported.");
20902 uint64_t
Offset = Shift / 8;
20905 "The size of the original loaded type is not a multiple of a"
20910 "Invalid shift amount for given loaded size");
20923 assert(Inst && Origin &&
"Unable to replace a non-existing slice.");
20927 int64_t
Offset =
static_cast<int64_t
>(getOffsetFromBase());
20928 assert(
Offset >= 0 &&
"Offset too big to fit in int64_t!");
20931 EVT ArithType =
BaseAddr.getValueType();
20938 EVT SliceType = getLoadedType();
20948 if (SliceType != FinalType)
20958 bool canMergeExpensiveCrossRegisterBankCopy()
const {
20964 assert(DAG &&
"Missing context");
20966 EVT ResVT =
User->getValueType(0);
20967 const TargetRegisterClass *ResRC =
20969 const TargetRegisterClass *ArgRC =
20971 User->getOperand(0)->isDivergent());
20980 if (!
TRI ||
TRI->getCommonSubClass(ArgRC, ResRC))
20985 unsigned IsFast = 0;
21026 const LoadedSlice &Second) {
21028 "Unable to match different memory origins.");
21030 assert((UsedBits & Second.getUsedBits()) == 0 &&
21031 "Slices are not supposed to overlap.");
21032 UsedBits |= Second.getUsedBits();
21041 LoadedSlice::Cost &GlobalLSCost) {
21042 unsigned NumberOfSlices = LoadedSlices.
size();
21044 if (NumberOfSlices < 2)
21049 llvm::sort(LoadedSlices, [](
const LoadedSlice &
LHS,
const LoadedSlice &
RHS) {
21050 assert(
LHS.Origin ==
RHS.Origin &&
"Different bases not implemented.");
21051 return LHS.getOffsetFromBase() <
RHS.getOffsetFromBase();
21053 const TargetLowering &TLI = LoadedSlices[0].DAG->getTargetLoweringInfo();
21056 const LoadedSlice *
First =
nullptr;
21057 const LoadedSlice *Second =
nullptr;
21058 for (
unsigned CurrSlice = 0; CurrSlice < NumberOfSlices; ++CurrSlice,
21061 Second = &LoadedSlices[CurrSlice];
21068 EVT LoadedType =
First->getLoadedType();
21071 if (LoadedType != Second->getLoadedType())
21075 Align RequiredAlignment;
21076 if (!TLI.hasPairedLoad(LoadedType, RequiredAlignment)) {
21082 if (
First->getAlign() < RequiredAlignment)
21089 assert(GlobalLSCost.Loads > 0 &&
"We save more loads than we created!");
21090 --GlobalLSCost.Loads;
21107 const APInt &UsedBits,
bool ForCodeSize) {
21108 unsigned NumberOfSlices = LoadedSlices.
size();
21110 return NumberOfSlices > 1;
21113 if (NumberOfSlices != 2)
21121 LoadedSlice::Cost OrigCost(ForCodeSize), GlobalSlicingCost(ForCodeSize);
21123 OrigCost.Loads = 1;
21124 for (
unsigned CurrSlice = 0; CurrSlice < NumberOfSlices; ++CurrSlice) {
21125 const LoadedSlice &LS = LoadedSlices[CurrSlice];
21127 LoadedSlice::Cost SliceCost(LS, ForCodeSize);
21128 GlobalSlicingCost += SliceCost;
21132 OrigCost.addSliceGain(LS);
21137 return OrigCost > GlobalSlicingCost;
21146bool DAGCombiner::SliceUpLoad(SDNode *
N) {
21152 !
LD->getValueType(0).isInteger())
21158 if (
LD->getValueType(0).isScalableVector())
21163 APInt UsedBits(
LD->getValueSizeInBits(0), 0);
21170 for (SDUse &U :
LD->uses()) {
21172 if (
U.getResNo() != 0)
21175 SDNode *
User =
U.getUser();
21176 unsigned Shift = 0;
21181 Shift =
User->getConstantOperandVal(1);
21194 unsigned Width =
User->getValueSizeInBits(0);
21199 LoadedSlice
LS(User, LD, Shift, &DAG);
21200 APInt CurrentUsedBits =
LS.getUsedBits();
21203 if ((CurrentUsedBits & UsedBits) != 0)
21206 UsedBits |= CurrentUsedBits;
21227 for (
const LoadedSlice &LS : LoadedSlices) {
21229 CombineTo(
LS.Inst, SliceInst,
true);
21233 "It takes more than a zext to get to the loaded slice!!");
21240 AddToWorklist(Chain.
getNode());
21247static std::pair<unsigned, unsigned>
21249 std::pair<unsigned, unsigned> Result(0, 0);
21259 if (LD->getBasePtr() != Ptr)
return Result;
21262 if (V.getValueType() != MVT::i16 &&
21263 V.getValueType() != MVT::i32 &&
21264 V.getValueType() != MVT::i64)
21272 if (NotMaskLZ & 7)
return Result;
21274 if (NotMaskTZ & 7)
return Result;
21275 if (NotMaskLZ == 64)
return Result;
21282 if (V.getValueType() != MVT::i64 && NotMaskLZ)
21283 NotMaskLZ -= 64-V.getValueSizeInBits();
21285 unsigned MaskedBytes = (V.getValueSizeInBits()-NotMaskLZ-NotMaskTZ)/8;
21286 switch (MaskedBytes) {
21290 default:
return Result;
21295 if (NotMaskTZ && NotMaskTZ/8 % MaskedBytes)
return Result;
21302 SDValue(LD, 1).hasOneUse()) {
21304 if (!LD->isOperandOf(Chain.
getNode()))
21309 Result.first = MaskedBytes;
21310 Result.second = NotMaskTZ/8;
21321 unsigned NumBytes = MaskInfo.first;
21322 unsigned ByteShift = MaskInfo.second;
21328 ByteShift*8, (ByteShift+NumBytes)*8);
21337 bool UseTruncStore;
21338 if (DC->isTypeLegal(VT))
21339 UseTruncStore =
false;
21342 UseTruncStore =
true;
21368 StOffset = ByteShift;
21396SDValue DAGCombiner::ReduceLoadOpStoreWidth(SDNode *
N) {
21398 if (!
ST->isSimple())
21404 EVT VT =
Value.getValueType();
21406 if (
ST->isTruncatingStore() || VT.
isVector())
21412 !
Value.hasOneUse())
21421 std::pair<unsigned, unsigned> MaskedLoad;
21423 if (MaskedLoad.first)
21425 Value.getOperand(1), ST,
this))
21430 if (MaskedLoad.first)
21432 Value.getOperand(0), ST,
this))
21446 if (
LD->getBasePtr() != Ptr ||
21447 LD->getPointerInfo().getAddrSpace() !=
21448 ST->getPointerInfo().getAddrSpace())
21457 if (Imm == 0 ||
Imm.isAllOnes())
21462 unsigned BitsPerByteMask = 7u;
21463 unsigned LSB =
Imm.countr_zero() & ~BitsPerByteMask;
21464 unsigned MSB = (
Imm.getActiveBits() - 1) | BitsPerByteMask;
21492 unsigned ShAmt = 0;
21493 uint64_t PtrOff = 0;
21494 for (; ShAmt + NewBW <= VTStoreSize; ShAmt += 8) {
21498 if (ShAmt + NewBW < MSB)
21503 ? VTStoreSize - NewBW - ShAmt
21505 PtrOff = PtrAdjustmentInBits / 8;
21508 unsigned IsFast = 0;
21511 LD->getAddressSpace(), NewAlign,
21512 LD->getMemOperand()->getFlags(), &IsFast) &&
21517 if (ShAmt + NewBW > VTStoreSize)
21520 APInt NewImm =
Imm.lshr(ShAmt).trunc(NewBW);
21527 DAG.
getLoad(NewVT, SDLoc(N0),
LD->getChain(), NewPtr,
21528 LD->getPointerInfo().getWithOffset(PtrOff), NewAlign,
21529 LD->getMemOperand()->getFlags(),
LD->getAAInfo());
21533 DAG.
getStore(Chain, SDLoc(
N), NewVal, NewPtr,
21534 ST->getPointerInfo().getWithOffset(PtrOff), NewAlign);
21536 AddToWorklist(NewPtr.
getNode());
21537 AddToWorklist(NewLD.
getNode());
21538 AddToWorklist(NewVal.
getNode());
21539 WorklistRemover DeadNodes(*
this);
21551SDValue DAGCombiner::TransformFPLoadStorePair(SDNode *
N) {
21555 Value.hasOneUse()) {
21557 EVT VT =
LD->getMemoryVT();
21559 LD->isNonTemporal() ||
ST->isNonTemporal() ||
21560 LD->getPointerInfo().getAddrSpace() != 0 ||
21561 ST->getPointerInfo().getAddrSpace() != 0)
21571 unsigned FastLD = 0, FastST = 0;
21578 *
LD->getMemOperand(), &FastLD) ||
21580 *
ST->getMemOperand(), &FastST) ||
21581 !FastLD || !FastST)
21585 LD->getBasePtr(),
LD->getMemOperand());
21588 ST->getBasePtr(),
ST->getMemOperand());
21590 AddToWorklist(NewLD.
getNode());
21591 AddToWorklist(NewST.
getNode());
21592 WorklistRemover DeadNodes(*
this);
21614bool DAGCombiner::isMulAddWithConstProfitable(SDNode *MulNode,
SDValue AddNode,
21623 for (SDNode *User : ConstNode->
users()) {
21624 if (User == MulNode)
21632 if (
User->getOperand(0) == ConstNode)
21633 OtherOp =
User->getOperand(1).getNode();
21635 OtherOp =
User->getOperand(0).getNode();
21647 if (OtherOp == MulVar)
21674SDValue DAGCombiner::getMergeStoreChains(SmallVectorImpl<MemOpLink> &StoreNodes,
21675 unsigned NumStores) {
21677 SmallPtrSet<const SDNode *, 8> Visited;
21678 SDLoc StoreDL(StoreNodes[0].MemNode);
21680 for (
unsigned i = 0; i < NumStores; ++i) {
21681 Visited.
insert(StoreNodes[i].MemNode);
21685 for (
unsigned i = 0; i < NumStores; ++i) {
21686 if (Visited.
insert(StoreNodes[i].MemNode->getChain().getNode()).second)
21687 Chains.
push_back(StoreNodes[i].MemNode->getChain());
21690 assert(!Chains.
empty() &&
"Chain should have generated a chain");
21695 const Value *UnderlyingObj =
nullptr;
21696 for (
const auto &MemOp : StoreNodes) {
21697 const MachineMemOperand *MMO = MemOp.MemNode->getMemOperand();
21708 if (UnderlyingObj && UnderlyingObj != Obj)
21711 if (!UnderlyingObj)
21712 UnderlyingObj =
Obj;
21718bool DAGCombiner::mergeStoresOfConstantsOrVecElts(
21719 SmallVectorImpl<MemOpLink> &StoreNodes, EVT MemVT,
unsigned NumStores,
21720 bool IsConstantSrc,
bool UseVector,
bool UseTrunc) {
21725 assert((!UseTrunc || !UseVector) &&
21726 "This optimization cannot emit a vector truncating store");
21729 SDLoc
DL(StoreNodes[0].MemNode);
21732 unsigned SizeInBits = NumStores * ElementSizeBits;
21735 std::optional<MachineMemOperand::Flags>
Flags;
21737 for (
unsigned I = 0;
I != NumStores; ++
I) {
21753 unsigned Elts = NumStores * NumMemElts;
21761 if (IsConstantSrc) {
21763 for (
unsigned I = 0;
I != NumStores; ++
I) {
21782 .zextOrTrunc(ElementSizeBits),
21783 SDLoc(
C), IntMemVT);
21792 DL, StoreTy, BuildVector);
21795 for (
unsigned i = 0; i < NumStores; ++i) {
21819 Val = DAG.
getNode(OpC, SDLoc(Val), MemVT, Vec, Idx);
21822 Ops.push_back(Val);
21833 assert(IsConstantSrc &&
"Merged vector elements should use vector store");
21835 APInt StoreInt(SizeInBits, 0);
21840 for (
unsigned i = 0; i < NumStores; ++i) {
21841 unsigned Idx = IsLE ? (NumStores - 1 - i) : i;
21846 StoreInt <<= ElementSizeBits;
21848 StoreInt |=
C->getAPIntValue()
21849 .zextOrTrunc(ElementSizeBits)
21850 .zextOrTrunc(SizeInBits);
21852 StoreInt |=
C->getValueAPF()
21854 .zextOrTrunc(ElementSizeBits)
21855 .zextOrTrunc(SizeInBits);
21872 LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
21873 SDValue NewChain = getMergeStoreChains(StoreNodes, NumStores);
21874 bool CanReusePtrInfo = hasSameUnderlyingObj(StoreNodes);
21888 FirstInChain->
getAlign(), *Flags, AAInfo);
21890 EVT LegalizedStoredValTy =
21892 unsigned LegalizedStoreSize = LegalizedStoredValTy.
getSizeInBits();
21895 DAG.
getConstant(
C->getAPIntValue().zextOrTrunc(LegalizedStoreSize),
DL,
21896 LegalizedStoredValTy);
21898 NewChain,
DL, ExtendedStoreVal, FirstInChain->
getBasePtr(),
21907 for (
unsigned i = 0; i < NumStores; ++i)
21908 CombineTo(StoreNodes[i].MemNode, NewStore);
21910 AddToWorklist(NewChain.
getNode());
21915DAGCombiner::getStoreMergeCandidates(StoreSDNode *St,
21916 SmallVectorImpl<MemOpLink> &StoreNodes) {
21921 if (!
BasePtr.getBase().getNode() ||
BasePtr.getBase().isUndef())
21925 StoreSource StoreSrc = getStoreSource(Val);
21926 assert(StoreSrc != StoreSource::Unknown &&
"Expected known source for store");
21930 BaseIndexOffset LBasePtr;
21932 if (StoreSrc == StoreSource::Load) {
21935 LoadVT = Ld->getMemoryVT();
21937 if (MemVT != LoadVT)
21940 if (!Ld->hasNUsesOfValue(1, 0))
21944 if (!Ld->isSimple() || Ld->isIndexed())
21947 auto CandidateMatch = [&](StoreSDNode *
Other, BaseIndexOffset &Ptr,
21948 int64_t &
Offset) ->
bool {
21951 if (!
Other->isSimple() ||
Other->isIndexed())
21961 :
Other->getMemoryVT() != MemVT;
21962 switch (StoreSrc) {
21963 case StoreSource::Load: {
21971 if (LoadVT != OtherLd->getMemoryVT())
21974 if (!OtherLd->hasNUsesOfValue(1, 0))
21978 if (!OtherLd->isSimple() || OtherLd->isIndexed())
21986 if (!(LBasePtr.equalBaseIndex(LPtr, DAG)))
21990 case StoreSource::Constant:
21993 if (getStoreSource(OtherBC) != StoreSource::Constant)
21996 case StoreSource::Extract:
21998 if (
Other->isTruncatingStore())
22031 if (ChainsWithoutMergeableStores.
contains(RootNode))
22036 auto OverLimitInDependenceCheck = [&](SDNode *StoreNode,
22037 SDNode *RootNode) ->
bool {
22038 auto RootCount = StoreRootCountMap.
find(StoreNode);
22039 return RootCount != StoreRootCountMap.
end() &&
22040 RootCount->second.first == RootNode &&
22044 auto TryToAddCandidate = [&](SDUse &
Use) {
22046 if (
Use.getOperandNo() != 0)
22049 BaseIndexOffset Ptr;
22051 if (CandidateMatch(OtherStore, Ptr, PtrDiff) &&
22052 !OverLimitInDependenceCheck(OtherStore, RootNode))
22053 StoreNodes.
push_back(MemOpLink(OtherStore, PtrDiff));
22057 unsigned NumNodesExplored = 0;
22058 const unsigned MaxSearchNodes = 1024;
22060 RootNode = Ldn->getChain().getNode();
22062 if (ChainsWithoutMergeableStores.
contains(RootNode))
22065 I !=
E && NumNodesExplored < MaxSearchNodes; ++
I, ++NumNodesExplored) {
22066 SDNode *
User =
I->getUser();
22068 for (SDUse &U2 :
User->uses())
22069 TryToAddCandidate(U2);
22073 TryToAddCandidate(*
I);
22078 I !=
E && NumNodesExplored < MaxSearchNodes; ++
I, ++NumNodesExplored)
22079 TryToAddCandidate(*
I);
22088bool DAGCombiner::checkMergeStoreCandidatesForDependencies(
22089 SmallVectorImpl<MemOpLink> &StoreNodes,
unsigned NumStores,
22090 SDNode *RootNode) {
22096 SmallPtrSet<const SDNode *, 32> Visited;
22104 while (!Worklist.
empty()) {
22106 if (!Visited.
insert(
N).second)
22115 unsigned int Max = 1024 + Visited.
size();
22117 for (
unsigned i = 0; i < NumStores; ++i) {
22118 SDNode *
N = StoreNodes[i].MemNode;
22139 for (
unsigned i = 0; i < NumStores; ++i)
22145 if (Visited.
size() >= Max) {
22146 auto &RootCount = StoreRootCountMap[StoreNodes[i].MemNode];
22147 if (RootCount.first == RootNode)
22148 RootCount.second++;
22150 RootCount = {RootNode, 1};
22157bool DAGCombiner::hasCallInLdStChain(StoreSDNode *St, LoadSDNode *Ld) {
22158 SmallPtrSet<const SDNode *, 32> Visited;
22162 while (!Worklist.
empty()) {
22164 if (!Visited.
insert(Node).second ||
Node->getNumOperands() == 0)
22167 switch (
Node->getOpcode()) {
22180 assert(
Node->getOperand(0).getValueType() == MVT::Other &&
22181 "Invalid chain type");
22190DAGCombiner::getConsecutiveStores(SmallVectorImpl<MemOpLink> &StoreNodes,
22191 int64_t ElementSizeBytes)
const {
22194 size_t StartIdx = 0;
22195 while ((StartIdx + 1 < StoreNodes.
size()) &&
22196 StoreNodes[StartIdx].OffsetFromBase + ElementSizeBytes !=
22197 StoreNodes[StartIdx + 1].OffsetFromBase)
22201 if (StartIdx + 1 >= StoreNodes.
size())
22210 unsigned NumConsecutiveStores = 1;
22211 int64_t StartAddress = StoreNodes[0].OffsetFromBase;
22214 for (
unsigned i = 1, e = StoreNodes.
size(); i < e; ++i) {
22215 int64_t CurrAddress = StoreNodes[i].OffsetFromBase;
22216 if (CurrAddress - StartAddress != (ElementSizeBytes * i))
22218 NumConsecutiveStores = i + 1;
22220 if (NumConsecutiveStores > 1)
22221 return NumConsecutiveStores;
22229bool DAGCombiner::tryStoreMergeOfConstants(
22230 SmallVectorImpl<MemOpLink> &StoreNodes,
unsigned NumConsecutiveStores,
22231 EVT MemVT, SDNode *RootNode,
bool AllowVectors) {
22236 bool MadeChange =
false;
22239 while (NumConsecutiveStores >= 2) {
22240 LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
22243 unsigned LastLegalType = 1;
22244 unsigned LastLegalVectorType = 1;
22245 bool LastIntegerTrunc =
false;
22246 bool NonZero =
false;
22247 unsigned FirstZeroAfterNonZero = NumConsecutiveStores;
22248 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
22251 bool IsElementZero =
false;
22253 IsElementZero =
C->isZero();
22255 IsElementZero =
C->getConstantFPValue()->isNullValue();
22257 IsElementZero =
true;
22258 if (IsElementZero) {
22259 if (NonZero && FirstZeroAfterNonZero == NumConsecutiveStores)
22260 FirstZeroAfterNonZero = i;
22262 NonZero |= !IsElementZero;
22265 unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
22267 unsigned IsFast = 0;
22279 LastIntegerTrunc =
false;
22280 LastLegalType = i + 1;
22284 EVT LegalizedStoredValTy =
22292 LastIntegerTrunc =
true;
22293 LastLegalType = i + 1;
22302 unsigned Elts = (i + 1) * NumMemElts;
22309 LastLegalVectorType = i + 1;
22313 bool UseVector = (LastLegalVectorType > LastLegalType) && AllowVectors;
22314 unsigned NumElem = (UseVector) ? LastLegalVectorType : LastLegalType;
22315 bool UseTrunc = LastIntegerTrunc && !UseVector;
22327 unsigned NumSkip = 1;
22328 while ((NumSkip < NumConsecutiveStores) &&
22329 (NumSkip < FirstZeroAfterNonZero) &&
22330 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
22334 NumConsecutiveStores -= NumSkip;
22339 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
22342 NumConsecutiveStores -= NumElem;
22346 MadeChange |= mergeStoresOfConstantsOrVecElts(StoreNodes, MemVT, NumElem,
22348 UseVector, UseTrunc);
22352 NumConsecutiveStores -= NumElem;
22357bool DAGCombiner::tryStoreMergeOfExtracts(
22358 SmallVectorImpl<MemOpLink> &StoreNodes,
unsigned NumConsecutiveStores,
22359 EVT MemVT, SDNode *RootNode) {
22363 bool MadeChange =
false;
22366 while (NumConsecutiveStores >= 2) {
22367 LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
22370 unsigned NumStoresToMerge = 1;
22371 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
22373 unsigned Elts = (i + 1) * NumMemElts;
22375 unsigned IsFast = 0;
22386 NumStoresToMerge = i + 1;
22391 if (NumStoresToMerge < 2) {
22398 unsigned NumSkip = 1;
22399 while ((NumSkip < NumConsecutiveStores) &&
22400 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
22404 NumConsecutiveStores -= NumSkip;
22409 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumStoresToMerge,
22412 StoreNodes.
begin() + NumStoresToMerge);
22413 NumConsecutiveStores -= NumStoresToMerge;
22417 MadeChange |= mergeStoresOfConstantsOrVecElts(
22418 StoreNodes, MemVT, NumStoresToMerge,
false,
22421 StoreNodes.
erase(StoreNodes.
begin(), StoreNodes.
begin() + NumStoresToMerge);
22422 NumConsecutiveStores -= NumStoresToMerge;
22427bool DAGCombiner::tryStoreMergeOfLoads(SmallVectorImpl<MemOpLink> &StoreNodes,
22428 unsigned NumConsecutiveStores, EVT MemVT,
22429 SDNode *RootNode,
bool AllowVectors,
22430 bool IsNonTemporalStore,
22431 bool IsNonTemporalLoad) {
22436 bool MadeChange =
false;
22443 BaseIndexOffset LdBasePtr;
22445 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
22452 int64_t LdOffset = 0;
22453 if (LdBasePtr.
getBase().getNode()) {
22455 if (!LdBasePtr.equalBaseIndex(LdPtr, DAG, LdOffset))
22463 LoadNodes.
push_back(MemOpLink(Ld, LdOffset));
22466 while (NumConsecutiveStores >= 2 && LoadNodes.
size() >= 2) {
22467 Align RequiredAlignment;
22468 bool NeedRotate =
false;
22469 if (LoadNodes.
size() == 2) {
22473 StoreNodes[0].MemNode->getAlign() >= RequiredAlignment) {
22479 int64_t Offset0 = LoadNodes[0].OffsetFromBase;
22480 int64_t Offset1 = LoadNodes[1].OffsetFromBase;
22482 if (Offset0 - Offset1 == ElementSizeBytes &&
22489 LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
22498 unsigned LastConsecutiveLoad = 1;
22501 unsigned LastLegalVectorType = 1;
22502 unsigned LastLegalIntegerType = 1;
22503 bool isDereferenceable =
true;
22504 bool DoIntegerTruncate =
false;
22505 int64_t StartAddress = LoadNodes[0].OffsetFromBase;
22507 for (
unsigned i = 1; i < LoadNodes.
size(); ++i) {
22509 if (LoadNodes[i].MemNode->getChain() != LoadChain)
22512 int64_t CurrAddress = LoadNodes[i].OffsetFromBase;
22513 if (CurrAddress - StartAddress != (ElementSizeBytes * i))
22515 LastConsecutiveLoad = i;
22517 if (isDereferenceable && !LoadNodes[i].MemNode->isDereferenceable())
22518 isDereferenceable =
false;
22521 unsigned Elts = (i + 1) * NumMemElts;
22528 unsigned IsFastSt = 0;
22529 unsigned IsFastLd = 0;
22543 LastLegalVectorType = i + 1;
22547 unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
22558 LastLegalIntegerType = i + 1;
22559 DoIntegerTruncate =
false;
22576 LastLegalIntegerType = i + 1;
22577 DoIntegerTruncate =
true;
22585 LastLegalVectorType > LastLegalIntegerType && AllowVectors;
22586 unsigned LastLegalType =
22587 std::max(LastLegalVectorType, LastLegalIntegerType);
22591 unsigned NumElem = std::min(NumConsecutiveStores, LastConsecutiveLoad + 1);
22592 NumElem = std::min(LastLegalType, NumElem);
22603 unsigned NumSkip = 1;
22604 while ((NumSkip < LoadNodes.
size()) &&
22605 (LoadNodes[NumSkip].MemNode->getAlign() <= FirstLoadAlign) &&
22606 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
22610 NumConsecutiveStores -= NumSkip;
22615 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
22619 NumConsecutiveStores -= NumElem;
22628 unsigned Elts = NumElem * NumMemElts;
22631 unsigned SizeInBits = NumElem * ElementSizeBytes * 8;
22641 NumConsecutiveStores -= NumElem;
22645 SDLoc LoadDL(LoadNodes[0].MemNode);
22646 SDLoc StoreDL(StoreNodes[0].MemNode);
22651 SDValue NewStoreChain = getMergeStoreChains(StoreNodes, NumElem);
22652 bool CanReusePtrInfo = hasSameUnderlyingObj(StoreNodes);
22653 AddToWorklist(NewStoreChain.
getNode());
22658 if (IsNonTemporalLoad)
22670 if (UseVectorTy || !DoIntegerTruncate) {
22676 unsigned LoadWidth = ElementSizeBytes * 8 * 2;
22678 "Unexpected type for rotate-able load pair");
22685 NewStoreChain, StoreDL, StoreOp, FirstInChain->
getBasePtr(),
22687 : MachinePointerInfo(FirstStoreAS),
22688 FirstStoreAlign, StMMOFlags);
22695 FirstLoadAlign, LdMMOFlags);
22697 NewStoreChain, StoreDL, NewLoad, FirstInChain->
getBasePtr(),
22699 : MachinePointerInfo(FirstStoreAS),
22700 JointMemOpVT, FirstInChain->
getAlign(),
22705 for (
unsigned i = 0; i < NumElem; ++i) {
22713 for (
unsigned i = 0; i < NumElem; ++i) {
22714 SDValue Val = StoreNodes[i].MemNode->getOperand(1);
22715 CombineTo(StoreNodes[i].MemNode, NewStore);
22717 recursivelyDeleteUnusedNodes(Val.
getNode());
22723 NumConsecutiveStores -= NumElem;
22728bool DAGCombiner::mergeConsecutiveStores(StoreSDNode *St) {
22744 if (ElementSizeBytes * 8 != (int64_t)MemVT.
getSizeInBits())
22750 const StoreSource StoreSrc = getStoreSource(StoredVal);
22751 if (StoreSrc == StoreSource::Unknown)
22756 SDNode *RootNode = getStoreMergeCandidates(St, StoreNodes);
22759 if (StoreNodes.
size() < 2)
22765 return LHS.OffsetFromBase <
RHS.OffsetFromBase;
22769 Attribute::NoImplicitFloat);
22771 bool IsNonTemporalLoad = StoreSrc == StoreSource::Load &&
22781 bool MadeChange =
false;
22782 while (StoreNodes.
size() > 1) {
22783 unsigned NumConsecutiveStores =
22784 getConsecutiveStores(StoreNodes, ElementSizeBytes);
22786 if (NumConsecutiveStores == 0)
22790 assert(NumConsecutiveStores >= 2 &&
"Expected at least 2 stores");
22791 switch (StoreSrc) {
22792 case StoreSource::Constant:
22793 MadeChange |= tryStoreMergeOfConstants(StoreNodes, NumConsecutiveStores,
22794 MemVT, RootNode, AllowVectors);
22797 case StoreSource::Extract:
22798 MadeChange |= tryStoreMergeOfExtracts(StoreNodes, NumConsecutiveStores,
22802 case StoreSource::Load:
22803 MadeChange |= tryStoreMergeOfLoads(StoreNodes, NumConsecutiveStores,
22804 MemVT, RootNode, AllowVectors,
22805 IsNonTemporalStore, IsNonTemporalLoad);
22815 ChainsWithoutMergeableStores.
insert(RootNode);
22820SDValue DAGCombiner::replaceStoreChain(StoreSDNode *ST,
SDValue BetterChain) {
22825 if (
ST->isTruncatingStore()) {
22827 ST->getBasePtr(),
ST->getMemoryVT(),
22828 ST->getMemOperand());
22830 ReplStore = DAG.
getStore(BetterChain, SL,
ST->getValue(),
ST->getBasePtr(),
22831 ST->getMemOperand());
22836 MVT::Other,
ST->getChain(), ReplStore);
22839 AddToWorklist(Token.
getNode());
22842 return CombineTo(ST, Token,
false);
22845SDValue DAGCombiner::replaceStoreOfFPConstant(StoreSDNode *ST) {
22876 if ((
isTypeLegal(MVT::i32) && !LegalOperations &&
ST->isSimple()) ||
22879 bitcastToAPInt().getZExtValue(), SDLoc(CFP),
22881 return DAG.
getStore(Chain,
DL, Tmp, Ptr,
ST->getMemOperand());
22886 if ((TLI.
isTypeLegal(MVT::i64) && !LegalOperations &&
22890 getZExtValue(), SDLoc(CFP), MVT::i64);
22892 Ptr,
ST->getMemOperand());
22907 AAMDNodes AAInfo =
ST->getAAInfo();
22910 ST->getBaseAlign(), MMOFlags, AAInfo);
22913 ST->getPointerInfo().getWithOffset(4),
22914 ST->getBaseAlign(), MMOFlags, AAInfo);
22928SDValue DAGCombiner::replaceStoreOfInsertLoad(StoreSDNode *ST) {
22943 EltVT !=
Value.getOperand(0).getValueType().getVectorElementType())
22957 ST->getAlign(),
ST->getMemOperand()->getFlags(),
22962 MachinePointerInfo PointerInfo(
ST->getAddressSpace());
22968 unsigned COffset = CIdx->getSExtValue() * EltVT.
getSizeInBits() / 8;
22970 PointerInfo =
ST->getPointerInfo().getWithOffset(COffset);
22978 return DAG.
getStore(Chain,
DL, Elt, NewPtr, PointerInfo,
ST->getAlign(),
22979 ST->getMemOperand()->getFlags());
22982SDValue DAGCombiner::visitATOMIC_STORE(SDNode *
N) {
22986 EVT MemVT =
ST->getMemoryVT();
23005 SDValue StoredVal = Store->getValue();
23006 SDValue StorePtr = Store->getBasePtr();
23007 SDValue StoreOffset = Store->getOffset();
23008 EVT VT = Store->getMemoryVT();
23015 unsigned AddrSpace = Store->getAddressSpace();
23016 Align Alignment = Store->getAlign();
23023 SDValue Mask, OtherVec, LoadCh;
23042 Load->getAddressSpace() != AddrSpace)
23045 if (!Store->getChain().reachesChainWithoutSideEffects(LoadCh))
23049 Mask = DAG.
getNOT(Dl, Mask, Mask.getValueType());
23051 return DAG.
getMaskedStore(Store->getChain(), Dl, OtherVec, StorePtr,
23052 StoreOffset, Mask, VT, Store->getMemOperand(),
23053 Store->getAddressingMode());
23056SDValue DAGCombiner::visitSTORE(SDNode *
N) {
23065 ST->isUnindexed()) {
23066 EVT SVT =
Value.getOperand(0).getValueType();
23073 if (((!LegalOperations &&
ST->isSimple()) ||
23076 DAG, *
ST->getMemOperand())) {
23078 ST->getMemOperand());
23083 if (
Value.isUndef() &&
ST->isUnindexed() && !
ST->isVolatile())
23090 if (*Alignment >
ST->getAlign() &&
23091 isAligned(*Alignment,
ST->getSrcValueOffset())) {
23094 ST->getMemoryVT(), *Alignment,
23095 ST->getMemOperand()->getFlags(),
ST->getAAInfo());
23105 if (
SDValue NewST = TransformFPLoadStorePair(
N))
23109 if (
SDValue Store = mergeTruncStores(ST))
23112 if (
ST->isUnindexed()) {
23115 if (findBetterNeighborChains(ST)) {
23120 Chain =
ST->getChain();
23124 if (
ST->isTruncatingStore() &&
ST->isUnindexed() &&
23125 Value.getValueType().isInteger() &&
23132 Value.getOperand(0).getValueType() ==
ST->getMemoryVT() &&
23135 ST->getMemOperand());
23137 APInt TruncDemandedBits =
23139 ST->getMemoryVT().getScalarSizeInBits());
23143 AddToWorklist(
Value.getNode());
23159 return DAG.
getTruncStore(Chain, SDLoc(
N), Shorter, Ptr,
ST->getMemoryVT(),
23160 ST->getMemOperand());
23165 if (!Cst->isOpaque()) {
23166 const APInt &CValue = Cst->getAPIntValue();
23167 APInt NewVal = CValue & TruncDemandedBits;
23168 if (NewVal != CValue) {
23172 ST->getMemoryVT(),
ST->getMemOperand());
23186 ST->isUnindexed() &&
ST->isSimple() &&
23197 if (
SDValue NewST = replaceStoreOfInsertLoad(ST))
23202 if (
ST->isUnindexed() &&
ST->isSimple() &&
23203 ST1->isUnindexed() && ST1->isSimple()) {
23205 ST1->getValue() ==
Value &&
ST->getMemoryVT() == ST1->getMemoryVT() &&
23206 ST->getAddressSpace() == ST1->getAddressSpace()) {
23213 !ST1->getBasePtr().isUndef() &&
23214 ST->getAddressSpace() == ST1->getAddressSpace()) {
23219 if (
ST->getMemoryVT().isScalableVector() ||
23220 ST1->getMemoryVT().isScalableVector()) {
23221 if (ST1->getBasePtr() == Ptr &&
23223 ST->getMemoryVT().getStoreSize())) {
23224 CombineTo(ST1, ST1->getChain());
23234 if (STBase.contains(DAG,
ST->getMemoryVT().getFixedSizeInBits(),
23236 ST1->getMemoryVT().getFixedSizeInBits())) {
23237 CombineTo(ST1, ST1->getChain());
23249 Value->hasOneUse() &&
ST->isUnindexed() &&
23251 ST->getMemoryVT(), LegalOperations)) {
23253 Ptr,
ST->getMemoryVT(),
ST->getMemOperand());
23264 bool Changed = mergeConsecutiveStores(ST);
23274 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
23283 if (
SDValue NewSt = replaceStoreOfFPConstant(ST))
23291 return MaskedStore;
23293 return ReduceLoadOpStoreWidth(
N);
23296SDValue DAGCombiner::visitLIFETIME_END(SDNode *
N) {
23298 const BaseIndexOffset LifetimeEndBase(
N->getOperand(1),
SDValue(), 0,
false);
23302 while (!Chains.
empty()) {
23321 if (!
ST->isSimple() ||
ST->isIndexed())
23323 const TypeSize StoreSize =
ST->getMemoryVT().getStoreSize();
23332 if (LifetimeEndBase.contains(
23336 dbgs() <<
"\nwithin LIFETIME_END of : ";
23337 LifetimeEndBase.dump();
dbgs() <<
"\n");
23338 CombineTo(ST,
ST->getChain());
23375SDValue DAGCombiner::splitMergedValStore(StoreSDNode *ST) {
23381 if (!
ST->isSimple())
23414 !
Lo.getOperand(0).getValueType().isScalarInteger() ||
23415 Lo.getOperand(0).getValueSizeInBits() > HalfValBitSize ||
23417 !
Hi.getOperand(0).getValueType().isScalarInteger() ||
23418 Hi.getOperand(0).getValueSizeInBits() > HalfValBitSize)
23424 ?
Lo.getOperand(0).getValueType()
23425 :
Lo.getValueType();
23427 ?
Hi.getOperand(0).getValueType()
23428 :
Hi.getValueType();
23434 AAMDNodes AAInfo =
ST->getAAInfo();
23445 ST->getBaseAlign(), MMOFlags, AAInfo);
23450 St0,
DL,
Hi, Ptr,
ST->getPointerInfo().getWithOffset(HalfValBitSize / 8),
23451 ST->getBaseAlign(), MMOFlags, AAInfo);
23462 unsigned InsIndex) {
23471 int ElementOffset = -1;
23480 while (!ArgWorkList.
empty()) {
23483 std::tie(ArgOffset, ArgVal) = ArgWorkList.
pop_back_val();
23485 if (ArgVal == InsertVal0) {
23486 ElementOffset = ArgOffset;
23492 int CurrentArgOffset =
23496 CurrentArgOffset -= Step;
23502 assert(CurrentArgOffset == ArgOffset);
23508 if (ElementOffset == -1) {
23509 if (!
Y.isUndef() || InsertVal0.
getValueType() !=
Y.getValueType())
23511 ElementOffset = Mask.size();
23515 NewMask.
assign(Mask.begin(), Mask.end());
23517 assert(NewMask[InsIndex] < (
int)(2 * Mask.size()) && NewMask[InsIndex] >= 0 &&
23518 "NewMask[InsIndex] is out of bound");
23527SDValue DAGCombiner::mergeInsertEltWithShuffle(SDNode *
N,
unsigned InsIndex) {
23529 "Expected extract_vector_elt");
23530 SDValue InsertVal =
N->getOperand(1);
23541 SmallVector<int, 16> NewMask(Mask);
23546 return LegalShuffle;
23557SDValue DAGCombiner::combineInsertEltToShuffle(SDNode *
N,
unsigned InsIndex) {
23559 "Expected extract_vector_elt");
23577 if (NumSrcElts == 1)
23580 unsigned NumMaskVals = ExtendRatio * NumSrcElts;
23587 SmallVector<int, 16>
Mask(NumMaskVals);
23588 for (
unsigned i = 0; i != NumMaskVals; ++i) {
23589 if (i / NumSrcElts == InsIndex)
23590 Mask[i] = (i % NumSrcElts) + NumMaskVals;
23605 ConcatOps[0] = SubVec;
23611 AddToWorklist(PaddedSubV.
getNode());
23612 AddToWorklist(DestVecBC.
getNode());
23613 AddToWorklist(Shuf.
getNode());
23620SDValue DAGCombiner::combineInsertEltToLoad(SDNode *
N,
unsigned InsIndex) {
23621 EVT VT =
N->getValueType(0);
23633 return InsIndex == P.index() || P.value() < 0 ||
23634 (InsIndex == 0 && P.value() == (int)P.index() - 1) ||
23635 (InsIndex == VT.getVectorNumElements() - 1 &&
23636 P.value() == (int)P.index() + 1);
23642 unsigned Extend = 0;
23646 Extend =
Scalar.getOpcode();
23664 int EltSize = ScalarLoad->getValueType(0).getScalarSizeInBits();
23665 if (EltSize == 0 || EltSize % 8 != 0 || !ScalarLoad->isSimple() ||
23668 ScalarLoad->getAddressSpace() !=
VecLoad->getAddressSpace())
23673 if (InsIndex == 0) {
23684 unsigned IsFast = 0;
23688 NewAlign,
VecLoad->getMemOperand()->getFlags(),
23695 SDValue Ptr = ScalarLoad->getBasePtr();
23699 MachinePointerInfo PtrInfo =
23700 InsIndex == 0 ? ScalarLoad->getPointerInfo()
23701 :
VecLoad->getPointerInfo().getWithOffset(EltSize / 8);
23704 ScalarLoad->getChain(), Ptr, PtrInfo, NewAlign);
23710SDValue DAGCombiner::visitINSERT_VECTOR_ELT(SDNode *
N) {
23747 if (!IsByteSized) {
23754 auto IsTypeDefaultHandled = [
this](EVT VT) {
23762 if (IsTypeDefaultHandled(OldVT) && IsTypeDefaultHandled(VT)) {
23771 unsigned NumDynamic = 1;
23783 if (NumDynamic > 1) {
23799 PtrInfo, SmallestAlign);
23823 DAG.
getLoad(VT,
DL, Store, StackPtr, PtrInfo, SmallestAlign);
23838 unsigned Elt = IndexC->getZExtValue();
23841 if (NumElts == 1) {
23859 if (Elt < OtherElt) {
23863 AddToWorklist(NewOp.
getNode());
23869 if (
SDValue Shuf = mergeInsertEltWithShuffle(
N, Elt))
23872 if (
SDValue Shuf = combineInsertEltToShuffle(
N, Elt))
23875 if (
SDValue Shuf = combineInsertEltToLoad(
N, Elt))
23886 auto AddBuildVectorOp = [&](SmallVectorImpl<SDValue> &
Ops,
SDValue Elt,
23891 EVT EltVT = Elt.getValueType();
23892 MaxEltVT = MaxEltVT.
bitsGE(EltVT) ? MaxEltVT : EltVT;
23899 auto CanonicalizeBuildVector = [&](SmallVectorImpl<SDValue> &
Ops,
23900 bool FreezeUndef =
false) {
23901 assert(
Ops.size() == NumElts &&
"Unexpected vector size");
23917 for (
SDValue CurVec = InVec; CurVec;) {
23919 if (CurVec.isUndef())
23920 return CanonicalizeBuildVector(
Ops);
23924 return CanonicalizeBuildVector(
Ops,
true);
23928 for (
unsigned I = 0;
I != NumElts; ++
I)
23929 AddBuildVectorOp(
Ops, CurVec.getOperand(
I),
I);
23930 return CanonicalizeBuildVector(
Ops);
23935 AddBuildVectorOp(
Ops, CurVec.getOperand(0), 0);
23936 return CanonicalizeBuildVector(
Ops);
23942 if (CurIdx->getAPIntValue().ult(NumElts)) {
23943 unsigned Idx = CurIdx->getZExtValue();
23944 AddBuildVectorOp(
Ops, CurVec.getOperand(1), Idx);
23948 return CanonicalizeBuildVector(
Ops);
23950 CurVec = CurVec->getOperand(0);
23962 bool Merged =
true;
23966 SmallVector<int, 16> NewMask;
23971 Mask = std::move(NewMask);
23980 if (!LegalOperations) {
23993 unsigned MaskOpcode) {
23994 for (
unsigned I = 0;
I != NumElts; ++
I)
23996 return DAG.
getNode(MaskOpcode,
DL, VT, CurVec,
24016 for (
unsigned I = 0;
I != NumElts; ++
I)
24023 for (
unsigned I = 0;
I != NumElts; ++
I)
24027 return CanonicalizeBuildVector(
Ops);
24037 const SDLoc &
DL,
bool LegalTypes) {
24079 if (ResVT != MVT::i1 &&
24104bool DAGCombiner::refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
24126 "Original ISD::EXTRACT_VECTOR_ELT is undefinend?");
24130 EVT ScalarVT =
N->getValueType(0);
24146 Entry(Entry &&) =
default;
24147 Entry(SDNode *Producer_,
unsigned BitPos_,
int NumBits_)
24148 :
Producer(Producer_), BitPos(BitPos_), NumBits(NumBits_) {}
24151 Entry(
const Entry &) =
delete;
24152 Entry &operator=(
const Entry &) =
delete;
24153 Entry &operator=(Entry &&) =
delete;
24159 Worklist.
emplace_back(
N, VecEltBitWidth * IndexC->getZExtValue(),
24162 while (!Worklist.
empty()) {
24169 bool ProducerIsLeaf =
false;
24171 for (SDNode *User :
E.Producer->users()) {
24172 switch (
User->getOpcode()) {
24180 User->getValueSizeInBits(0));
24187 User->getOperand(0).getNode() ==
E.Producer && ShAmtC) {
24190 unsigned ShAmt = ShAmtC->getZExtValue();
24191 Worklist.
emplace_back(User,
E.BitPos + ShAmt,
E.NumBits - ShAmt);
24198 ProducerIsLeaf =
true;
24206 if (ProducerIsLeaf)
24210 unsigned NewVecEltBitWidth = Leafs.
front().NumBits;
24213 if (NewVecEltBitWidth == VecEltBitWidth)
24223 if (!
all_of(Leafs, [NewVecEltBitWidth](
const Entry &
E) {
24224 return (
unsigned)
E.NumBits == NewVecEltBitWidth &&
24225 E.Producer->getValueSizeInBits(0) == NewVecEltBitWidth &&
24226 E.BitPos % NewVecEltBitWidth == 0;
24238 if (LegalOperations &&
24244 for (
const Entry &
E : Leafs) {
24245 SDLoc
DL(
E.Producer);
24246 unsigned NewIndex =
E.BitPos / NewVecEltBitWidth;
24248 "Creating out-of-bounds ISD::EXTRACT_VECTOR_ELT?");
24251 CombineTo(
E.Producer, V);
24257SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *
N) {
24260 EVT ScalarVT =
N->getValueType(0);
24273 AddUsersToWorklist(VecOp.
getNode());
24308 "BUILD_VECTOR used for scalable vectors");
24309 unsigned IndexVal =
24317 if (ScalarVT == InEltVT)
24357 unsigned ExtractIndex = IndexC->getZExtValue();
24359 unsigned BCTruncElt = IsLE ? 0 : NumElts - 1;
24372 EVT XVT =
X.getValueType();
24374 "Extract element and scalar to vector can't change element type "
24375 "from FP to integer.");
24376 unsigned XBitWidth =
X.getValueSizeInBits();
24377 unsigned Scale = XBitWidth / VecEltBitWidth;
24378 BCTruncElt = IsLE ? 0 : Scale - 1;
24383 if (ExtractIndex < Scale && XBitWidth > VecEltBitWidth) {
24384 assert(XBitWidth % VecEltBitWidth == 0 &&
24385 "Scalar bitwidth must be a multiple of vector element bitwidth");
24387 if (ExtractIndex != BCTruncElt) {
24388 unsigned ShiftIndex =
24389 IsLE ? ExtractIndex : (Scale - 1) - ExtractIndex;
24409 int OrigElt = Shuf->getMaskElt(IndexC->getZExtValue());
24417 if (OrigElt < (
int)NumElts) {
24421 OrigElt -= NumElts;
24442 if (!LegalOperations ||
24454 return Use->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
24455 Use->getOperand(0) == VecOp &&
24456 isa<ConstantSDNode>(Use->getOperand(1));
24459 for (SDNode *User : VecOp->
users()) {
24461 if (CstElt->getAPIntValue().ult(NumElts))
24462 DemandedElts.
setBit(CstElt->getZExtValue());
24481 if (refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
N))
24487 bool BCNumEltsChanged =
false;
24502 BCNumEltsChanged =
true;
24508 if (!LegalOperations && !IndexC && VecOp.
hasOneUse() &&
24512 if (VecLoad &&
VecLoad->isSimple()) {
24514 ScalarVT, SDLoc(
N), VecVT, Index, VecLoad, DAG)) {
24523 if (!LegalOperations || !IndexC)
24529 int Elt = IndexC->getZExtValue();
24530 LoadSDNode *LN0 =
nullptr;
24553 if (BCNumEltsChanged)
24557 int Idx = (Elt > (int)NumElts) ? -1 : Shuf->getMaskElt(Elt);
24562 if (!VecOp.hasOneUse())
24565 VecOp = VecOp.getOperand(0);
24568 LN0 = cast<LoadSDNode>(VecOp);
24569 Elt = (Idx < (int)NumElts) ? Idx : Idx - (int)NumElts;
24570 Index = DAG.getConstant(Elt, DL, Index.getValueType());
24588 Index.getValueType());
24616SDValue DAGCombiner::reduceBuildVecExtToExtBuildVec(SDNode *
N) {
24626 unsigned NumInScalars =
N->getNumOperands();
24628 EVT VT =
N->getValueType(0);
24635 EVT SourceType = MVT::Other;
24636 bool AllAnyExt =
true;
24638 for (
unsigned i = 0; i != NumInScalars; ++i) {
24641 if (
In.isUndef())
continue;
24647 if (!ZeroExt && !AnyExt) {
24648 SourceType = MVT::Other;
24653 EVT InTy =
In.getOperand(0).getValueType();
24656 if (SourceType == MVT::Other)
24659 else if (InTy != SourceType) {
24661 SourceType = MVT::Other;
24666 AllAnyExt &= AnyExt;
24674 SourceType != MVT::Other &&
24690 assert(ElemRatio > 1 &&
"Invalid element size ratio");
24698 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
24702 Cast.
isUndef()) &&
"Invalid cast opcode");
24708 unsigned Index = isLE ? (i * ElemRatio) :
24709 (i * ElemRatio + (ElemRatio - 1));
24711 assert(Index <
Ops.size() &&
"Invalid index");
24718 "Invalid vector size");
24738SDValue DAGCombiner::reduceBuildVecTruncToBitCast(SDNode *
N) {
24741 EVT VT =
N->getValueType(0);
24759 unsigned NumInScalars =
N->getNumOperands();
24762 auto PeekThroughBitcast = [](
SDValue Op) {
24764 return Op.getOperand(0);
24770 for (
unsigned i = 0; i != NumInScalars; ++i) {
24771 SDValue In = PeekThroughBitcast(
N->getOperand(i));
24773 if (
In.isUndef())
continue;
24778 In = PeekThroughBitcast(
In.getOperand(0));
24789 SDValue part = PeekThroughBitcast(
In.getOperand(0));
24793 }
else if (Src != part) {
24798 SDValue ShiftAmtVal =
In.getOperand(1);
24802 uint64_t ShiftAmt =
In.getConstantOperandVal(1);
24805 if (ShiftAmt != i * ScalarTypeBitsize)
24811 if (!Src || Src.getValueType().getSizeInBits() != VT.
getSizeInBits())
24817SDValue DAGCombiner::createBuildVecShuffle(
const SDLoc &
DL, SDNode *
N,
24818 ArrayRef<int> VectorMask,
24820 unsigned LeftIdx,
bool DidSplitVec) {
24821 EVT VT =
N->getValueType(0);
24826 unsigned ShuffleNumElems = NumElems;
24836 assert(InVT2Size <= InVT1Size &&
24837 "Inputs must be sorted to be in non-increasing vector size order.");
24841 if (InVT1 != VT || InVT2 != VT) {
24842 if ((VTSize % InVT1Size == 0) && InVT1 == InVT2) {
24845 unsigned NumConcats = VTSize / InVT1Size;
24846 assert(NumConcats >= 2 &&
"Concat needs at least two inputs!");
24848 ConcatOps[0] = VecIn1;
24849 ConcatOps[1] = VecIn2 ? VecIn2 : DAG.
getUNDEF(InVT1);
24852 }
else if (InVT1Size == VTSize * 2) {
24864 Vec2Offset = NumElems;
24866 assert(InVT2Size <= InVT1Size &&
24867 "Second input is not going to be larger than the first one.");
24873 if (LegalOperations &&
24880 if (InVT1 != InVT2) {
24885 ShuffleNumElems = NumElems * 2;
24887 }
else if (InVT2Size * 2 == VTSize && InVT1Size == VTSize) {
24889 ConcatOps[0] = VecIn2;
24891 }
else if (InVT1Size / VTSize > 1 && InVT1Size % VTSize == 0) {
24899 assert(InVT2Size <= InVT1Size &&
24900 "Second input is not going to be larger than the first one.");
24909 if (InVT1 != InVT2) {
24912 ShuffleNumElems = InVT1Size / VTSize * NumElems;
24923 SmallVector<int, 8>
Mask(ShuffleNumElems, -1);
24928 for (
unsigned i = 0; i != NumElems; ++i) {
24929 if (VectorMask[i] <= 0)
24932 unsigned ExtIndex =
N->getOperand(i).getConstantOperandVal(1);
24933 if (VectorMask[i] == (
int)LeftIdx) {
24934 Mask[i] = ExtIndex;
24935 }
else if (VectorMask[i] == (
int)LeftIdx + 1) {
24936 Mask[i] = Vec2Offset + ExtIndex;
24949 if (ShuffleNumElems > NumElems)
24962 for (
int i = 0; i != NumBVOps; ++i) {
24994 if (DestSize % SrcSize != 0 ||
25000 int ZextRatio = DestSize / SrcSize;
25001 int NumMaskElts = NumBVOps * ZextRatio;
25003 for (
int i = 0; i != NumMaskElts; ++i) {
25004 if (i / ZextRatio == ZextElt) {
25025 ZeroVec, ShufMask, DAG);
25032template <
typename R,
typename T>
25036 return static_cast<decltype(std::distance(
Range.begin(),
I))
>(-1);
25037 return std::distance(
Range.begin(),
I);
25043SDValue DAGCombiner::reduceBuildVecToShuffle(SDNode *
N) {
25045 EVT VT =
N->getValueType(0);
25058 bool UsesZeroVector =
false;
25059 unsigned NumElems =
N->getNumOperands();
25067 SmallVector<int, 8> VectorMask(NumElems, -1);
25073 unsigned OneConstExtractIndex = ~0
u;
25076 unsigned NumExtracts = 0;
25078 for (
unsigned i = 0; i != NumElems; ++i) {
25088 UsesZeroVector =
true;
25098 SDValue ExtractedFromVec =
Op.getOperand(0);
25105 if (ExtractIdx->getAsAPIntVal().uge(
25114 OneConstExtractIndex = ExtractIdx->getZExtValue();
25122 Idx = VecIn.
size();
25126 VectorMask[i] = Idx;
25130 if (VecIn.
size() < 2)
25137 bool DidSplitVec =
false;
25138 if (VecIn.
size() == 2) {
25147 if (NumExtracts == 1 &&
25153 unsigned MaxIndex = 0;
25154 unsigned NearestPow2 = 0;
25157 SmallVector<unsigned, 8> IndexVec(NumElems, 0);
25159 for (
unsigned i = 0; i < NumElems; i++) {
25160 if (VectorMask[i] <= 0)
25162 unsigned Index =
N->getOperand(i).getConstantOperandVal(1);
25163 IndexVec[i] =
Index;
25164 MaxIndex = std::max(MaxIndex, Index);
25168 if (InVT.
isSimple() && NearestPow2 > 2 && MaxIndex < NearestPow2 &&
25169 NumElems * 2 < NearestPow2) {
25170 unsigned SplitSize = NearestPow2 / 2;
25183 DidSplitVec =
true;
25185 for (
unsigned i = 0; i < NumElems; i++) {
25186 if (VectorMask[i] <= 0)
25188 VectorMask[i] = (IndexVec[i] < SplitSize) ? 1 : 2;
25201 b.getValueType().getVectorNumElements();
25206 for (
int &SourceVectorIndex : VectorMask) {
25207 if (SourceVectorIndex <= 0)
25209 unsigned Idx =
getFirstIndexOf(SortedVecIn, VecIn[SourceVectorIndex]);
25210 assert(Idx > 0 && Idx < SortedVecIn.size() &&
25211 VecIn[SourceVectorIndex] == SortedVecIn[Idx] &&
"Remapping failure");
25212 SourceVectorIndex = Idx;
25215 VecIn = std::move(SortedVecIn);
25233 for (
unsigned In = 0, Len = (VecIn.
size() / 2); In < Len; ++In) {
25234 unsigned LeftIdx = 2 *
In + 1;
25235 SDValue VecLeft = VecIn[LeftIdx];
25237 (LeftIdx + 1) < VecIn.
size() ? VecIn[LeftIdx + 1] :
SDValue();
25239 if (
SDValue Shuffle = createBuildVecShuffle(
DL,
N, VectorMask, VecLeft,
25240 VecRight, LeftIdx, DidSplitVec))
25248 if (UsesZeroVector)
25253 if (Shuffles.
size() == 1)
25254 return Shuffles[0];
25257 for (
int &Vec : VectorMask)
25259 Vec = Shuffles.
size() - 1;
25261 Vec = (Vec - 1) / 2;
25275 if (Shuffles.
size() % 2)
25278 for (
unsigned CurSize = Shuffles.
size(); CurSize > 1; CurSize /= 2) {
25280 Shuffles[CurSize] = DAG.
getUNDEF(VT);
25283 for (
unsigned In = 0, Len = CurSize / 2;
In <
Len; ++
In) {
25286 SmallVector<int, 8>
Mask(NumElems, -1);
25288 ArrayRef<int> LMask;
25290 L.use_empty() &&
L.getOperand(1).isUndef() &&
25291 L.getOperand(0).getValueType() ==
L.getValueType();
25292 if (IsLeftShuffle) {
25294 L =
L.getOperand(0);
25297 ArrayRef<int> RMask;
25299 R.use_empty() &&
R.getOperand(1).isUndef() &&
25300 R.getOperand(0).getValueType() ==
R.getValueType();
25301 if (IsRightShuffle) {
25303 R =
R.getOperand(0);
25305 for (
unsigned I = 0;
I != NumElems; ++
I) {
25306 if (VectorMask[
I] ==
Left) {
25310 VectorMask[
I] =
In;
25311 }
else if (VectorMask[
I] ==
Right) {
25313 if (IsRightShuffle)
25314 Mask[
I] = RMask[
I] + NumElems;
25315 VectorMask[
I] =
In;
25322 return Shuffles[0];
25329SDValue DAGCombiner::convertBuildVecZextToZext(SDNode *
N) {
25330 if (LegalOperations)
25333 EVT VT =
N->getValueType(0);
25335 bool FoundZeroExtend =
false;
25337 auto checkElem = [&](
SDValue Op) -> int64_t {
25338 unsigned Opc =
Op.getOpcode();
25344 return C->getZExtValue();
25352 int64_t
Offset = checkElem(Op0);
25356 unsigned NumElems =
N->getNumOperands();
25358 EVT InSVT =
In.getValueType().getScalarType();
25366 for (
unsigned i = 1; i != NumElems; ++i) {
25367 if ((
Offset + i) != checkElem(
N->getOperand(i)))
25385SDValue DAGCombiner::convertBuildVecZextToBuildVecWithZeros(SDNode *
N) {
25394 EVT VT =
N->getValueType(0);
25395 EVT OpVT =
N->getOperand(0).getValueType();
25409 unsigned ActiveBits = 0;
25415 unsigned OpActiveBits =
25416 Cst->getAPIntValue().trunc(EltBitwidth).getActiveBits();
25417 if (OpActiveBits == 0) {
25418 KnownZeroOps.setBit(
I.index());
25426 if (
I.index() != 0)
25432 unsigned CurrActiveBits =
25433 Op.getOperand(0).getValueSizeInBits().getFixedValue();
25434 assert(!ActiveBits &&
"Already encountered non-constant-zero operand?");
25435 ActiveBits = CurrActiveBits;
25437 if (2 * ActiveBits > EltBitwidth)
25442 if (ActiveBits == 0)
25447 EVT NewScalarIntVT, NewIntVT;
25448 std::optional<unsigned> Factor;
25453 assert(2 * ActiveBits <= EltBitwidth &&
25454 "We know that half or less bits of the element are active.");
25455 for (
unsigned Scale = EltBitwidth / ActiveBits; Scale >= 2; --Scale) {
25456 if (EltBitwidth % Scale != 0)
25458 unsigned ChunkBitwidth = EltBitwidth / Scale;
25459 assert(ChunkBitwidth >= ActiveBits &&
"As per starting point.");
25462 Scale *
N->getNumOperands());
25464 (LegalOperations &&
25482 assert(!
Op.isUndef() &&
"FIXME: after allowing UNDEF's, handle them here.");
25483 unsigned SrcOpIdx =
I.index();
25484 if (KnownZeroOps[SrcOpIdx]) {
25485 NewOps.
append(*Factor, ZeroOp);
25491 NewOps.
append(*Factor - 1, ZeroOp);
25499SDValue DAGCombiner::visitBUILD_VECTOR(SDNode *
N) {
25500 EVT VT =
N->getValueType(0);
25514 if (!LegalOperations) {
25520 EVT SrcVT =
Splat.getValueType();
25536 if (!LegalTypes && (
N->getNumOperands() > 1)) {
25538 auto checkElem = [&](
SDValue Op) -> uint64_t {
25546 int Offset = checkElem(Op0);
25547 for (
unsigned i = 0; i <
N->getNumOperands(); ++i) {
25548 if (
Offset + i != checkElem(
N->getOperand(i))) {
25558 ((
Offset %
N->getValueType(0).getVectorNumElements()) ==
25564 if (
SDValue V = convertBuildVecZextToZext(
N))
25567 if (
SDValue V = convertBuildVecZextToBuildVecWithZeros(
N))
25570 if (
SDValue V = reduceBuildVecExtToExtBuildVec(
N))
25573 if (
SDValue V = reduceBuildVecTruncToBitCast(
N))
25576 if (
SDValue V = reduceBuildVecToShuffle(
N))
25583 assert(!
V.isUndef() &&
"Splat of undef should have been handled earlier");
25592 EVT OpVT =
N->getOperand(0).getValueType();
25599 EVT VT =
N->getValueType(0);
25608 !
Op.getOperand(0).getValueType().isVector())
25609 Ops.push_back(
Op.getOperand(0));
25610 else if (
Op.isUndef())
25617 EVT LastOpVT =
Ops.back().getValueType();
25619 AnyFPVT = LastOpVT;
25627 if (AnyFPVT !=
EVT()) {
25630 if (
Op.getValueType() == SVT)
25649 EVT VT =
N->getValueType(0);
25659 if (!FirstConcat) {
25660 SubVT =
Op.getOperand(0).getValueType();
25666 if (SubVT !=
Op.getOperand(0).getValueType())
25669 assert(FirstConcat &&
"Concat of all-undefs found");
25673 if (
Op.isUndef()) {
25677 ConcatOps.
append(
Op->op_begin(),
Op->op_end());
25687 EVT VT =
N->getValueType(0);
25688 EVT OpVT =
N->getOperand(0).getValueType();
25704 if (
Op.isUndef()) {
25705 Mask.append((
unsigned)NumOpElts, -1);
25714 int ExtIdx =
Op.getConstantOperandVal(1);
25723 Mask.append((
unsigned)NumOpElts, -1);
25734 if (0 == (NumExtElts % NumElts))
25735 ExtIdx /= (NumExtElts / NumElts);
25736 else if (0 == (NumElts % NumExtElts))
25737 ExtIdx *= (NumElts / NumExtElts);
25742 if (SV0.
isUndef() || SV0 == ExtVec) {
25744 for (
int i = 0; i != NumOpElts; ++i)
25745 Mask.push_back(i + ExtIdx);
25746 }
else if (SV1.
isUndef() || SV1 == ExtVec) {
25748 for (
int i = 0; i != NumOpElts; ++i)
25749 Mask.push_back(i + ExtIdx + NumElts);
25761 unsigned CastOpcode =
N->getOperand(0).getOpcode();
25762 switch (CastOpcode) {
25778 EVT SrcVT =
N->getOperand(0).getOperand(0).getValueType();
25786 if (
Op.getOpcode() != CastOpcode || !
Op.hasOneUse() ||
25787 Op.getOperand(0).getValueType() != SrcVT)
25795 EVT VT =
N->getValueType(0);
25800 switch (CastOpcode) {
25820 return DAG.
getNode(CastOpcode,
DL, VT, NewConcat);
25828 bool LegalOperations) {
25829 EVT VT =
N->getValueType(0);
25830 EVT OpVT =
N->getOperand(0).getValueType();
25835 if (
N->getNumOperands() != 2)
25840 (LegalOperations &&
25852 CurSVN && CurSVN->getOperand(1).
isUndef() &&
N->isOnlyUserOf(CurSVN) &&
25855 return !Op.isUndef() &&
25856 (Op.getNode() == CurSVN || is_contained(CurSVN->ops(), Op));
25877 std::iota(FirstShufOpIdentityMask.
begin(), FirstShufOpIdentityMask.
end(), 0);
25878 std::iota(SecondShufOpIdentityMask.
begin(), SecondShufOpIdentityMask.
end(),
25885 assert(!
Op.isUndef() &&
"Not expecting to concatenate UNDEF.");
25886 if (
Op.getNode() == SVN) {
25907 std::array<SDValue, 2> ShufOps;
25908 for (
auto I :
zip(SVN->
ops(), ShufOps)) {
25910 SDValue &NewShufOp = std::get<1>(
I);
25916 ShufOpParts[0] = ShufOp;
25927 bool LegalOperations) {
25928 EVT VT =
N->getValueType(0);
25946SDValue DAGCombiner::visitCONCAT_VECTORS(SDNode *
N) {
25948 if (
N->getNumOperands() == 1)
25952 EVT VT =
N->getValueType(0);
25958 [](
const SDValue &
Op) { return Op.isUndef(); })) {
25960 assert(
In.getValueType().isVector() &&
"Must concat vectors");
25970 !(LegalDAG &&
In.getValueType().isScalableVector())) {
25971 unsigned NumOps =
N->getNumOperands() *
In.getNumOperands();
25983 EVT SVT =
Scalar.getValueType().getVectorElementType();
25984 if (SVT ==
Scalar.getOperand(0).getValueType())
25989 if (!
Scalar.getValueType().isVector() &&
In.hasOneUse()) {
25998 EVT SclTy =
Scalar.getValueType();
26008 if (VNTNumElms < 2)
26024 auto IsBuildVectorOrUndef = [](
const SDValue &
Op) {
26035 bool FoundMinVT =
false;
26038 EVT OpSVT =
Op.getOperand(0).getValueType();
26039 MinVT = (!FoundMinVT || OpSVT.
bitsLE(MinVT)) ? OpSVT : MinVT;
26042 assert(FoundMinVT &&
"Concat vector type mismatch");
26046 EVT OpVT =
Op.getValueType();
26055 Opnds.
append(
Op->op_begin(),
Op->op_begin() + NumElts);
26057 for (
unsigned i = 0; i != NumElts; ++i)
26065 "Concat vector type mismatch");
26092 N, DAG, TLI, LegalTypes, LegalOperations))
26102 unsigned PartNumElem =
26103 N->getOperand(0).getValueType().getVectorMinNumElements();
26105 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
26116 if (SingleSource.
getNode()) {
26117 if (
Op.getOperand(0) != SingleSource)
26120 SingleSource =
Op.getOperand(0);
26130 unsigned IdentityIndex = i * PartNumElem;
26131 if (
Op.getConstantOperandAPInt(1) != IdentityIndex)
26136 return SingleSource;
26141SDValue DAGCombiner::visitVECTOR_INTERLEAVE(SDNode *
N) {
26152 Ops.append(
N->op_values().begin(),
N->op_values().end());
26153 return CombineTo(
N, &
Ops);
26160 V.getOperand(1).getValueType() == SubVT &&
26161 V.getConstantOperandAPInt(2) == Index) {
26162 return V.getOperand(1);
26165 V.getOperand(0).getValueType() == SubVT &&
26168 return V.getOperand(SubIdx);
26174 unsigned Index,
const SDLoc &
DL,
26176 bool LegalOperations) {
26178 unsigned BinOpcode = BinOp.
getOpcode();
26184 if (VecVT != Bop0.
getValueType() || VecVT != Bop1.getValueType())
26195 if (!Sub0 || !Sub1)
26208 bool LegalOperations) {
26229 if (
C &&
C->getValueAPF().isNegZero())
26242 "Extract index is not a multiple of the vector length.");
26247 if (WideWidth % NarrowWidth != 0)
26252 unsigned NarrowingRatio = WideWidth / NarrowWidth;
26254 if (WideNumElts % NarrowingRatio != 0)
26259 WideNumElts / NarrowingRatio);
26271 BinOp.
hasOneUse() && Src->hasOneUse()) {
26285 if (NarrowingRatio != 2)
26300 return V.getOperand(ConcatOpNum);
26306 if (SubVecL || SubVecR) {
26357 assert(Index % NumElts == 0 &&
"The extract subvector index is not a "
26358 "multiple of the result's element count");
26362 std::optional<unsigned> ByteOffset;
26364 ByteOffset =
Offset.getFixedValue();
26376 if (
Offset.isScalable()) {
26400 bool LegalOperations) {
26402 EVT WideVT = Src.getValueType();
26408 if (!WideShuffleVector)
26412 if (!WideShuffleVector->hasOneUse())
26417 if (LegalOperations &&
26422 assert((Index % NumEltsExtracted) == 0 &&
26423 "Extract index is not a multiple of the output vector length.");
26428 NewMask.
reserve(NumEltsExtracted);
26430 DemandedSubvectors;
26433 for (
int M : WideShuffleVector->getMask().slice(Index, NumEltsExtracted)) {
26434 assert((M >= -1) && (M < (2 * WideNumElts)) &&
26435 "Out-of-bounds shuffle mask?");
26444 int WideShufOpIdx = M / WideNumElts;
26446 int OpEltIdx = M % WideNumElts;
26448 assert((OpEltIdx + WideShufOpIdx * WideNumElts) == M &&
26449 "Shuffle mask vector decomposition failure.");
26452 int OpSubvecIdx = OpEltIdx / NumEltsExtracted;
26454 int OpEltIdxInSubvec = OpEltIdx % NumEltsExtracted;
26456 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted) == OpEltIdx &&
26457 "Shuffle mask subvector decomposition failure.");
26459 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted +
26460 WideShufOpIdx * WideNumElts) == M &&
26461 "Shuffle mask full decomposition failure.");
26463 SDValue Op = WideShuffleVector->getOperand(WideShufOpIdx);
26465 if (
Op.isUndef()) {
26471 const std::pair<SDValue, int> DemandedSubvector =
26472 std::make_pair(
Op, OpSubvecIdx);
26474 if (DemandedSubvectors.insert(DemandedSubvector)) {
26475 if (DemandedSubvectors.size() > 2)
26478 int Index = NumEltsExtracted * OpSubvecIdx;
26486 getFirstIndexOf(DemandedSubvectors.getArrayRef(), DemandedSubvector);
26487 assert((NewOpIdx == 0 || NewOpIdx == 1) &&
"Unexpected operand index.");
26489 int AdjM = OpEltIdxInSubvec + NewOpIdx * NumEltsExtracted;
26492 assert(NewMask.
size() == (
unsigned)NumEltsExtracted &&
"Produced bad mask.");
26493 assert(DemandedSubvectors.size() <= 2 &&
26494 "Should have ended up demanding at most two subvectors.");
26497 if (DemandedSubvectors.empty())
26503 any_of(NewMask, [](
int M) {
return M < 0; }))
26504 for (
auto &DemandedSubvector : DemandedSubvectors)
26505 if (DemandedSubvector.second != 0)
26517 for (
const std::pair<SDValue /*Op*/, int /*SubvectorIndex*/>
26518 &DemandedSubvector : DemandedSubvectors) {
26520 int Index = NumEltsExtracted * DemandedSubvector.second;
26523 DemandedSubvector.first, IndexC));
26526 "Should end up with either one or two ops");
26529 if (NewOps.
size() == 1)
26535SDValue DAGCombiner::visitEXTRACT_SUBVECTOR(SDNode *
N) {
26536 EVT NVT =
N->getValueType(0);
26538 uint64_t ExtIdx =
N->getConstantOperandVal(1);
26555 V.getConstantOperandVal(1)) &&
26575 unsigned InsIdx =
V.getConstantOperandVal(2);
26577 if (InsIdx <= ExtIdx && (ExtIdx + NumSubElts) <= (InsIdx + NumInsElts) &&
26580 V.getValueType().isFixedLengthVector())
26588 V.getOperand(0).getValueType().isVector() &&
26593 unsigned DestNumElts =
V.getValueType().getVectorMinNumElements();
26594 if ((SrcNumElts % DestNumElts) == 0) {
26595 unsigned SrcDestRatio = SrcNumElts / DestNumElts;
26602 V.getOperand(0), NewIndex);
26606 if ((DestNumElts % SrcNumElts) == 0) {
26607 unsigned DestSrcRatio = DestNumElts / SrcNumElts;
26609 ElementCount NewExtEC =
26612 if ((ExtIdx % DestSrcRatio) == 0) {
26613 unsigned IndexValScaled = ExtIdx / DestSrcRatio;
26620 V.getOperand(0), NewIndex);
26628 V.getOperand(0), NewIndex);
26638 EVT ConcatSrcVT =
V.getOperand(0).getValueType();
26640 "Concat and extract subvector do not change element type");
26643 unsigned ConcatOpIdx = ExtIdx / ConcatSrcNumElts;
26649 return V.getOperand(ConcatOpIdx);
26657 ConcatSrcNumElts % ExtNumElts == 0) {
26658 unsigned NewExtIdx = ExtIdx - ConcatOpIdx * ConcatSrcNumElts;
26659 assert(NewExtIdx + ExtNumElts <= ConcatSrcNumElts &&
26660 "Trying to extract from >1 concat operand?");
26661 assert(NewExtIdx % ExtNumElts == 0 &&
26662 "Extract index is not a multiple of the input vector length.");
26665 V.getOperand(ConcatOpIdx), NewIndexC);
26670 NVT, V, ExtIdx,
DL, DAG, LegalOperations))
26681 EVT InVT =
V.getValueType();
26685 if (ExtractSize % EltSize == 0) {
26686 unsigned NumElems = ExtractSize / EltSize;
26689 NumElems == 1 ? EltVT
26697 if (NumElems == 1) {
26698 SDValue Src =
V->getOperand(IdxVal);
26699 if (EltVT != Src.getValueType())
26715 EVT SmallVT =
V.getOperand(1).getValueType();
26716 if (NVT.
bitsEq(SmallVT)) {
26722 uint64_t InsIdx =
V.getConstantOperandVal(2);
26730 DAG.
getBitcast(
N->getOperand(0).getValueType(),
V.getOperand(0)),
26738 if (!
V.getValueType().isScalableVector() &&
26740 return Use->getOpcode() == ISD::EXTRACT_SUBVECTOR &&
26741 Use->getOperand(0) == V;
26743 unsigned NumElts =
V.getValueType().getVectorNumElements();
26745 for (SDNode *User :
V->users()) {
26746 unsigned ExtIdx =
User->getConstantOperandVal(1);
26747 unsigned NumSubElts =
User->getValueType(0).getVectorNumElements();
26748 DemandedElts.
setBits(ExtIdx, ExtIdx + NumSubElts);
26782 unsigned HalfNumElts = NumElts / 2;
26785 for (
unsigned i = 0; i != NumElts; ++i) {
26789 if ((Mask[i] % NumElts) >= HalfNumElts)
26791 int M = Mask[i] < (int)NumElts ? Mask[i] : Mask[i] - (int)HalfNumElts;
26792 if (i < HalfNumElts)
26795 Mask1[i - HalfNumElts] = M;
26818 EVT VT =
N->getValueType(0);
26829 unsigned NumConcats = NumElts / NumElemsPerConcat;
26831 auto IsUndefMaskElt = [](
int i) {
return i == -1; };
26836 if (NumElemsPerConcat * 2 == NumElts && N1.
isUndef() &&
26837 llvm::all_of(Mask.slice(NumElemsPerConcat, NumElemsPerConcat),
26841 Mask.slice(0, NumElemsPerConcat));
26848 for (
unsigned I = 0;
I != NumConcats; ++
I) {
26849 unsigned Begin =
I * NumElemsPerConcat;
26850 ArrayRef<int> SubMask = Mask.slice(Begin, NumElemsPerConcat);
26859 for (
int i = 0; i != (int)NumElemsPerConcat; ++i) {
26860 if (IsUndefMaskElt(SubMask[i]))
26862 if ((SubMask[i] % (
int)NumElemsPerConcat) != i)
26864 int EltOpIdx = SubMask[i] / NumElemsPerConcat;
26869 assert(0 <=
OpIdx &&
"Unknown concat_vectors op");
26923 bool IsSplat =
false;
26927 if (
SDValue Splat0 = BV0->getSplatValue())
26928 IsSplat = (Splat0 == BV1->getSplatValue());
26932 for (
int M : SVN->
getMask()) {
26935 int Idx = M < (int)NumElts ? M : M - NumElts;
26936 SDValue &S = (M < (int)NumElts ? N0 : N1);
26953 if (!IsSplat && !DuplicateOps.
insert(
Op).second)
26964 SVT = (SVT.
bitsLT(
Op.getValueType()) ?
Op.getValueType() : SVT);
26980 unsigned Opcode,
EVT VT, std::function<
bool(
unsigned)> Match,
26982 bool LegalOperations) {
26987 return std::nullopt;
26995 for (
unsigned Scale = 2; Scale < NumElts; Scale *= 2) {
26997 if (NumElts % Scale != 0)
27011 return std::nullopt;
27020 bool LegalOperations) {
27030 Mask = SVN->
getMask()](
unsigned Scale) {
27031 for (
unsigned i = 0; i != NumElts; ++i) {
27034 if ((i % Scale) == 0 && Mask[i] == (
int)(i / Scale))
27046 Opcode, VT, isAnyExtend, DAG, TLI,
true, LegalOperations);
27058 bool LegalOperations) {
27059 bool LegalTypes =
true;
27071 auto ForEachDecomposedIndice = [NumElts, &Mask](
auto Fn) {
27072 for (
int &Indice : Mask) {
27076 int OpEltIdx = (
unsigned)Indice < NumElts ? Indice : Indice - NumElts;
27077 Fn(Indice,
OpIdx, OpEltIdx);
27082 std::array<APInt, 2> OpsDemandedElts;
27083 for (
APInt &OpDemandedElts : OpsDemandedElts)
27085 ForEachDecomposedIndice(
27086 [&OpsDemandedElts](
int &Indice,
int OpIdx,
int OpEltIdx) {
27087 OpsDemandedElts[
OpIdx].setBit(OpEltIdx);
27091 std::array<APInt, 2> OpsKnownZeroElts;
27092 for (
auto I :
zip(SVN->
ops(), OpsDemandedElts, OpsKnownZeroElts))
27100 bool HadZeroableElts =
false;
27101 ForEachDecomposedIndice([&OpsKnownZeroElts, &HadZeroableElts](
27102 int &Indice,
int OpIdx,
int OpEltIdx) {
27103 if (OpsKnownZeroElts[
OpIdx][OpEltIdx]) {
27105 HadZeroableElts =
true;
27113 if (!HadZeroableElts)
27121 Mask.size() % ScaledMask.
size() == 0 &&
"Unexpected mask widening.");
27122 int Prescale = Mask.size() / ScaledMask.
size();
27124 NumElts = ScaledMask.
size();
27125 EltSizeInBits *= Prescale;
27137 auto isZeroExtend = [NumElts, &ScaledMask](
unsigned Scale) {
27138 assert(Scale >= 2 && Scale <= NumElts && NumElts % Scale == 0 &&
27139 "Unexpected mask scaling factor.");
27141 for (
unsigned SrcElt = 0, NumSrcElts = NumElts / Scale;
27142 SrcElt != NumSrcElts; ++SrcElt) {
27145 assert(MaskChunk.
size() == Scale &&
"Unexpected mask size.");
27146 Mask = Mask.drop_front(MaskChunk.
size());
27149 if (
int FirstIndice = MaskChunk[0]; (
unsigned)FirstIndice != SrcElt)
27154 [](
int Indice) { return Indice == -2; }))
27157 assert(Mask.empty() &&
"Did not process the whole mask?");
27162 for (
bool Commuted : {
false,
true}) {
27167 Opcode, PrescaledVT, isZeroExtend, DAG, TLI, LegalTypes,
27203 if (ExtDstSizeInBits % ExtSrcSizeInBits != 0)
27205 unsigned ExtScale = ExtDstSizeInBits / ExtSrcSizeInBits;
27210 auto isTruncate = [&Mask, &NumElts](
unsigned Scale) {
27211 for (
unsigned i = 0; i != NumElts; ++i) {
27214 if ((i * Scale) < NumElts && Mask[i] == (
int)(i * Scale))
27224 if (EltSizeInBits != ExtSrcSizeInBits)
27231 if (isTruncate(ExtScale))
27254 APInt DemandedElts(NumElts, 0);
27255 for (
int Idx : Shuf->
getMask()) {
27258 assert((
unsigned)Idx < NumElts &&
"Out-of-bounds shuffle indice?");
27259 DemandedElts.
setBit(Idx);
27261 assert(DemandedElts.
popcount() > 1 &&
"Is a splat shuffle already?");
27266 std::optional<unsigned> MinNonUndefIdx;
27267 for (
int Idx : Shuf->
getMask()) {
27268 if (Idx < 0 || UndefElts[Idx])
27270 MinNonUndefIdx = std::min<unsigned>(Idx, MinNonUndefIdx.value_or(~0U));
27272 if (!MinNonUndefIdx)
27274 assert(*MinNonUndefIdx < NumElts &&
"Expected valid element index.");
27276 for (
int &Idx : SplatMask) {
27281 Idx = UndefElts[Idx] ? -1 : *MinNonUndefIdx;
27283 assert(SplatMask != Shuf->
getMask() &&
"Expected mask to change!");
27301 assert(ShufMask.
size() == SplatMask.
size() &&
"Mask length mismatch");
27319 auto CanSimplifyToExistingSplat = [](
ArrayRef<int> UserMask,
27321 for (
unsigned i = 0, e = UserMask.
size(); i != e; ++i)
27322 if (UserMask[i] != -1 && SplatMask[i] == -1 &&
27323 SplatMask[UserMask[i]] != -1)
27327 if (CanSimplifyToExistingSplat(ShufMask, SplatMask))
27333 for (
int Idx : ShufMask)
27334 NewMask.
push_back(Idx == -1 ? -1 : SplatMask[Idx]);
27346 bool LegalOperations) {
27363 if (VTLanes <= InLanes || VTLanes % InLanes != 0 ||
27364 (LegalOperations &&
27367 int Factor = VTLanes / InLanes;
27395 if (!InnerShuf || !InnerShuf->getOperand(1).isUndef())
27400 unsigned NumElts = OuterMask.
size();
27401 assert(NumElts == InnerMask.
size() &&
"Mask length mismatch");
27403 int SplatIndex = -1;
27404 for (
unsigned i = 0; i != NumElts; ++i) {
27406 int OuterMaskElt = OuterMask[i];
27407 if (OuterMaskElt == -1)
27411 int InnerMaskElt = InnerMask[OuterMaskElt];
27412 if (InnerMaskElt == -1)
27416 if (SplatIndex == -1)
27417 SplatIndex = InnerMaskElt;
27420 if (SplatIndex != InnerMaskElt)
27423 CombinedMask[i] = InnerMaskElt;
27425 assert((
all_of(CombinedMask, [](
int M) {
return M == -1; }) ||
27427 "Expected a splat mask");
27431 assert(VT == InnerShuf->getValueType(0) &&
"Expected matching shuffle types");
27436 InnerShuf->getOperand(1), CombinedMask);
27444 int MaskSize = Mask.size();
27445 int EltFromOp0 = -1;
27450 for (
int i = 0; i != MaskSize; ++i) {
27451 if (Mask[i] >= 0 && Mask[i] < MaskSize) {
27453 if (EltFromOp0 != -1)
27456 }
else if (Mask[i] != i + MaskSize) {
27467SDValue DAGCombiner::replaceShuffleOfInsert(ShuffleVectorSDNode *Shuf) {
27471 SmallVector<int, 16> CommutedMask(Mask);
27475 if (ShufOp0Index == -1) {
27479 if (ShufOp0Index == -1)
27483 Mask = CommutedMask;
27491 assert(Mask[ShufOp0Index] >= 0 && Mask[ShufOp0Index] < (
int)
Mask.size() &&
27492 "Shuffle mask value must be from operand 0");
27510 Op1, Elt, NewInsIndex);
27517 Mask[ShufOp0Index] == 0) {
27520 Op1, Elt, NewInsIndex);
27538 for (
int i = 0, e = (
int)Mask.size(); i != e; ++i) {
27542 assert(Mask[i] >= 0 && Mask[i] < e &&
"Unexpected shuffle mask value");
27546 if (Mask0[Mask[i]] != Mask0[i])
27554SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *
N) {
27555 EVT VT =
N->getValueType(0);
27581 SmallVector<int, 8> NewMask;
27582 for (
unsigned i = 0; i != NumElts; ++i) {
27584 if (Idx >= (
int)NumElts) {
27594 if (
SDValue InsElt = replaceShuffleOfInsert(SVN))
27634 if (Idx->getAPIntValue() == SplatIndex)
27660 SDValue ConvInput =
V->getOperand(0);
27667 assert(
V->getNumOperands() == NumElts &&
27668 "BUILD_VECTOR has wrong number of operands");
27670 bool AllSame =
true;
27671 for (
unsigned i = 0; i != NumElts; ++i) {
27672 if (!
V->getOperand(i).isUndef()) {
27673 Base =
V->getOperand(i);
27678 if (!
Base.getNode())
27680 for (
unsigned i = 0; i != NumElts; ++i) {
27681 if (
V->getOperand(i) !=
Base) {
27692 SDValue Splatted =
V->getOperand(SplatIndex);
27696 for (
unsigned i = 0; i != NumElts; ++i) {
27705 if (
V->getValueType(0) != VT)
27744 int HalfNumElts = (int)NumElts / 2;
27745 SmallVector<int, 8> NewMask;
27746 for (
unsigned i = 0; i != NumElts; ++i) {
27748 if (Idx >= HalfNumElts) {
27749 assert(Idx < (
int)NumElts &&
"Shuffle mask chooses undef op");
27750 Idx -= HalfNumElts;
27771 EVT SubVT =
RHS.getOperand(0).getValueType();
27772 int NumSubVecs =
RHS.getNumOperands();
27774 assert((NumElts % NumSubElts) == 0 &&
"Subvector mismatch");
27779 if (
all_of(Mask, [NumElts](
int M) {
return M < (int)NumElts; }))
27784 SmallVector<int> InsertionMask(NumElts);
27785 for (
int SubVec = 0; SubVec != NumSubVecs; ++SubVec) {
27786 for (
int SubIdx = 0; SubIdx != (int)NumElts; SubIdx += NumSubElts) {
27788 std::iota(InsertionMask.begin(), InsertionMask.end(), 0);
27791 std::iota(InsertionMask.begin() + SubIdx,
27792 InsertionMask.begin() + SubIdx + NumSubElts,
27793 NumElts + (SubVec * NumSubElts));
27796 bool MatchingShuffle =
true;
27797 for (
int i = 0; i != (int)NumElts; ++i) {
27798 int ExpectIdx = InsertionMask[i];
27799 int ActualIdx =
Mask[i];
27800 if (0 <= ActualIdx && ExpectIdx != ActualIdx) {
27801 MatchingShuffle =
false;
27806 if (MatchingShuffle)
27815 if (
SDValue InsertN1 = ShuffleToInsert(N0, N1, Mask))
27818 SmallVector<int> CommuteMask(Mask);
27820 if (
SDValue InsertN0 = ShuffleToInsert(N1, N0, CommuteMask))
27828 bool IsInLaneMask =
true;
27830 SmallVector<int, 16> ClearMask(NumElts, -1);
27833 for (
int I = 0;
I != (int)NumElts; ++
I) {
27837 ClearMask[
I] =
M ==
I ?
I : (
I + NumElts);
27838 IsInLaneMask &= (
M ==
I) || (M == (
int)(
I + NumElts));
27840 APInt &Demanded =
M < (int)NumElts ? DemandedLHS : DemandedRHS;
27841 Demanded.
setBit(M % NumElts);
27845 if (!IsInLaneMask && (!DemandedLHS.
isZero() || !DemandedRHS.
isZero()) &&
27860 for (
int I = 0;
I != (int)NumElts; ++
I)
27862 AndMask[
I] =
Mask[
I] ==
I ? AllOnesElt : ZeroElt;
27899 EVT ScaleVT = SVT.
bitsLT(InnerSVT) ? VT : InnerVT;
27910 SmallVector<int, 8> InnerMask;
27911 SmallVector<int, 8> OuterMask;
27916 SmallVector<int, 8> NewMask;
27917 for (
int M : OuterMask)
27918 NewMask.
push_back(M < 0 ? -1 : InnerMask[M]);
27949 auto MergeInnerShuffle =
27950 [NumElts, &VT](
bool Commute, ShuffleVectorSDNode *SVN,
27951 ShuffleVectorSDNode *OtherSVN,
SDValue N1,
27953 SmallVectorImpl<int> &
Mask) ->
bool {
27956 if (OtherSVN->isSplat())
27962 for (
unsigned i = 0; i != NumElts; ++i) {
27963 int Idx = SVN->getMaskElt(i);
27966 Mask.push_back(Idx);
27971 Idx = (Idx < (int)NumElts) ? (Idx + NumElts) : (Idx - NumElts);
27974 if (Idx < (
int)NumElts) {
27977 Idx = OtherSVN->getMaskElt(Idx);
27980 Mask.push_back(Idx);
27983 CurrentVec = (Idx < (int)NumElts) ? OtherSVN->
getOperand(0)
27992 Mask.push_back(-1);
27998 Idx = Idx % NumElts;
27999 if (!SV0.getNode() || SV0 == CurrentVec) {
28003 Mask.push_back(Idx);
28006 if (!SV1.getNode() || SV1 == CurrentVec) {
28010 Mask.push_back(Idx + NumElts);
28017 int InnerIdx = CurrentSVN->getMaskElt(Idx);
28018 if (InnerIdx < 0) {
28019 Mask.push_back(-1);
28022 SDValue InnerVec = (InnerIdx < (int)NumElts)
28023 ? CurrentSVN->getOperand(0)
28024 : CurrentSVN->getOperand(1);
28026 Mask.push_back(-1);
28029 InnerIdx %= NumElts;
28030 if (InnerVec == SV0) {
28031 Mask.push_back(InnerIdx);
28034 if (InnerVec == SV1) {
28035 Mask.push_back(InnerIdx + NumElts);
28054 if (TLI.isShuffleMaskLegal(Mask, VT))
28059 return TLI.isShuffleMaskLegal(Mask, VT);
28071 assert(N1->getOperand(0).getValueType() == VT &&
28072 "Shuffle types don't match");
28074 SDValue SV0 = N1->getOperand(0);
28075 SDValue SV1 = N1->getOperand(1);
28076 bool HasSameOp0 = N0 == SV0;
28077 bool IsSV1Undef = SV1.
isUndef();
28078 if (HasSameOp0 || IsSV1Undef || N0 == SV1)
28099 for (
int i = 0; i != 2; ++i) {
28101 N->isOnlyUserOf(
N->getOperand(i).getNode())) {
28105 assert(OtherSV->getOperand(0).getValueType() == VT &&
28106 "Shuffle types don't match");
28109 SmallVector<int, 4>
Mask;
28110 if (MergeInnerShuffle(i != 0, SVN, OtherSV,
N->getOperand(1 - i), TLI,
28118 SV1 ? SV1 : DAG.
getUNDEF(VT), Mask);
28128 if (TLI.isBinOp(SrcOpcode) &&
N->isOnlyUserOf(N0.
getNode()) &&
28130 (SrcOpcode == N1.getOpcode() &&
N->isOnlyUserOf(N1.getNode())))) {
28135 SDValue Op11 = N1.isUndef() ? N1 : N1.getOperand(1);
28146 SmallVectorImpl<int> &
Mask,
bool LeftOp,
28148 SDValue InnerN = Commute ? N1 : N0;
28149 SDValue Op0 = LeftOp ? Op00 : Op01;
28150 SDValue Op1 = LeftOp ? Op10 : Op11;
28157 MergeInnerShuffle(Commute, SVN, SVN0, Op1, TLI, SV0, SV1,
28159 (
llvm::any_of(SVN0->getMask(), [](
int M) { return M < 0; }) ||
28165 bool MergedLeft =
false;
28167 SmallVector<int, 4> LeftMask;
28168 if (CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
false) ||
28169 CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
true)) {
28172 LeftMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
28173 LeftSV0 = Op00, LeftSV1 = Op10;
28176 bool MergedRight =
false;
28178 SmallVector<int, 4> RightMask;
28179 if (CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
false) ||
28180 CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
true)) {
28181 MergedRight =
true;
28183 RightMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
28184 RightSV0 = Op01, RightSV1 = Op11;
28187 if (MergedLeft || MergedRight) {
28190 VT,
DL, LeftSV0 ? LeftSV0 : DAG.
getUNDEF(VT),
28191 LeftSV1 ? LeftSV1 : DAG.
getUNDEF(VT), LeftMask);
28193 VT,
DL, RightSV0 ? RightSV0 : DAG.
getUNDEF(VT),
28194 RightSV1 ? RightSV1 : DAG.
getUNDEF(VT), RightMask);
28215SDValue DAGCombiner::visitSCALAR_TO_VECTOR(SDNode *
N) {
28216 EVT VT =
N->getValueType(0);
28226 unsigned Opcode =
Scalar.getOpcode();
28228 if (
Scalar.hasOneUse() &&
Scalar->getNumValues() == 1 &&
28229 TLI.isBinOp(Opcode) &&
Scalar.getValueType() == VecEltVT &&
28230 Scalar.getOperand(0).getValueType() == VecEltVT &&
28231 Scalar.getOperand(1).getValueType() == VecEltVT &&
28232 Scalar->isOnlyUserOf(
Scalar.getOperand(0).getNode()) &&
28233 Scalar->isOnlyUserOf(
Scalar.getOperand(1).getNode()) &&
28238 for (
int i : {0, 1}) {
28249 if (TLI.isShuffleMaskLegal(ShufMask, VT)) {
28264 !
Scalar.getOperand(0).getValueType().isFixedLengthVector())
28268 if (VecEltVT !=
Scalar.getValueType() &&
28282 if (VecEltVT == SrcVT.
getScalarType() && VTNumElts <= SrcNumElts) {
28284 SmallVector<int, 8>
Mask(SrcNumElts, -1);
28285 Mask[0] = ExtIndexC->getZExtValue();
28286 SDValue LegalShuffle = TLI.buildLegalVectorShuffle(
28287 SrcVT, SDLoc(
N), SrcVec, DAG.
getUNDEF(SrcVT), Mask, DAG);
28293 return LegalShuffle;
28296 if (VTNumElts != SrcNumElts) {
28308SDValue DAGCombiner::visitINSERT_SUBVECTOR(SDNode *
N) {
28309 EVT VT =
N->getValueType(0);
28313 uint64_t InsIdx =
N->getConstantOperandVal(2);
28337 InsIdx + SubVecNumElts);
28434 if ((N0.
isUndef() || N0SrcSVT == N1SrcSVT) &&
28446 }
else if ((N1SrcSVT.
getSizeInBits() % EltSizeInBits) == 0) {
28469 if (InsIdx < OtherIdx) {
28473 AddToWorklist(NewOp.
getNode());
28487 Ops[InsIdx / Factor] = N1;
28498SDValue DAGCombiner::visitFP_TO_FP16(SDNode *
N) {
28508SDValue DAGCombiner::visitFP16_TO_FP(SDNode *
N) {
28509 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
28510 auto Op =
N->getOpcode();
28512 "opcode should be FP16_TO_FP or BF16_TO_FP.");
28525 return CastEliminated;
28531 N->getValueType(0), {N0});
28535SDValue DAGCombiner::visitFP_TO_BF16(SDNode *
N) {
28545SDValue DAGCombiner::visitBF16_TO_FP(SDNode *
N) {
28547 return visitFP16_TO_FP(
N);
28550SDValue DAGCombiner::visitVECREDUCE(SDNode *
N) {
28553 unsigned Opcode =
N->getOpcode();
28571 if (!TLI.isOperationLegalOrCustom(Opcode, VT) &&
28572 TLI.isOperationLegalOrCustom(NewOpcode, VT) &&
28574 return DAG.
getNode(NewOpcode, SDLoc(
N),
N->getValueType(0), N0);
28587 return DAG.
getNode(Opcode, SDLoc(
N),
N->getValueType(0), Subvec);
28606SDValue DAGCombiner::visitVP_FSUB(SDNode *
N) {
28607 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
28610 if (
SDValue Fused = visitFSUBForFMACombine<VPMatchContext>(
N)) {
28611 AddToWorklist(Fused.getNode());
28617SDValue DAGCombiner::visitVPOp(SDNode *
N) {
28619 if (
N->getOpcode() == ISD::VP_GATHER)
28620 if (
SDValue SD = visitVPGATHER(
N))
28623 if (
N->getOpcode() == ISD::VP_SCATTER)
28624 if (
SDValue SD = visitVPSCATTER(
N))
28627 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_LOAD)
28628 if (
SDValue SD = visitVP_STRIDED_LOAD(
N))
28631 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_STORE)
28632 if (
SDValue SD = visitVP_STRIDED_STORE(
N))
28638 bool AreAllEltsDisabled =
false;
28642 AreAllEltsDisabled |=
28646 if (!AreAllEltsDisabled) {
28647 switch (
N->getOpcode()) {
28649 return visitVP_FADD(
N);
28651 return visitVP_FSUB(
N);
28653 return visitFMA<VPMatchContext>(
N);
28654 case ISD::VP_SELECT:
28655 return visitVP_SELECT(
N);
28657 return visitMUL<VPMatchContext>(
N);
28668 return DAG.
getUNDEF(
N->getValueType(0));
28673 if (MemSD->writeMem())
28674 return MemSD->getChain();
28675 return CombineTo(
N, DAG.
getUNDEF(
N->getValueType(0)), MemSD->getChain());
28685SDValue DAGCombiner::visitGET_FPENV_MEM(SDNode *
N) {
28692 LoadSDNode *LdNode =
nullptr;
28693 for (
auto *U : Ptr->
users()) {
28697 if (LdNode && LdNode != Ld)
28710 StoreSDNode *StNode =
nullptr;
28711 for (SDUse &U : LdNode->
uses()) {
28712 if (
U.getResNo() == 0) {
28731 CombineTo(StNode, Res,
false);
28735SDValue DAGCombiner::visitSET_FPENV_MEM(SDNode *
N) {
28741 StoreSDNode *StNode =
nullptr;
28742 for (
auto *U : Ptr->
users()) {
28746 if (StNode && StNode != St)
28779SDValue DAGCombiner::XformToShuffleWithZero(SDNode *
N) {
28782 EVT VT =
N->getValueType(0);
28789 if (LegalOperations)
28795 EVT RVT =
RHS.getValueType();
28796 unsigned NumElts =
RHS.getNumOperands();
28801 auto BuildClearMask = [&](
int Split) {
28802 int NumSubElts = NumElts *
Split;
28805 SmallVector<int, 8> Indices;
28806 for (
int i = 0; i != NumSubElts; ++i) {
28807 int EltIdx = i /
Split;
28808 int SubIdx = i %
Split;
28824 Bits->extractBits(NumSubBits, (Split - SubIdx - 1) * NumSubBits);
28826 *
Bits =
Bits->extractBits(NumSubBits, SubIdx * NumSubBits);
28828 if (
Bits->isAllOnes())
28830 else if (*Bits == 0)
28839 if (!TLI.isVectorClearMaskLegal(Indices, ClearVT))
28853 for (
int Split = 1;
Split <= MaxSplit; ++
Split)
28855 if (
SDValue S = BuildClearMask(Split))
28864 const SDLoc &
DL,
bool LegalTypes) {
28867 unsigned Opcode =
N->getOpcode();
28868 EVT VT =
N->getValueType(0);
28875 int Index0, Index1;
28882 if (!Src0 || !Src1 || Index0 != Index1 ||
28909 for (
auto [
X,
Y] :
zip(EltsX, EltsY))
28924SDValue DAGCombiner::SimplifyVCastOp(SDNode *
N,
const SDLoc &
DL) {
28925 EVT VT =
N->getValueType(0);
28926 assert(VT.
isVector() &&
"SimplifyVCastOp only works on vectors!");
28928 unsigned Opcode =
N->getOpcode();
28959SDValue DAGCombiner::SimplifyVBinOp(SDNode *
N,
const SDLoc &
DL) {
28960 EVT VT =
N->getValueType(0);
28961 assert(VT.
isVector() &&
"SimplifyVBinOp only works on vectors!");
28965 unsigned Opcode =
N->getOpcode();
28966 SDNodeFlags
Flags =
N->getFlags();
28978 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
28979 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
28982 RHS.getOperand(0), Flags);
28994 Shuf0->hasOneUse() && Shuf0->getOperand(1).isUndef() &&
29003 Shuf1->hasOneUse() && Shuf1->getOperand(1).isUndef() &&
29019 LHS.getOperand(2) ==
RHS.getOperand(2) &&
29024 EVT NarrowVT =
X.getValueType();
29025 if (NarrowVT ==
Y.getValueType() &&
29027 LegalOperations)) {
29040 return Op.isUndef() ||
29041 ISD::isBuildVectorOfConstantSDNodes(Op.getNode());
29050 if (ConcatWithConstantOrUndef(
LHS) && ConcatWithConstantOrUndef(
RHS) &&
29052 EVT NarrowVT =
LHS.getOperand(0).getValueType();
29053 if (NarrowVT ==
RHS.getOperand(0).getValueType() &&
29055 unsigned NumOperands =
LHS.getNumOperands();
29057 for (
unsigned i = 0; i != NumOperands; ++i) {
29060 RHS.getOperand(i)));
29076 "First argument must be a SetCC node!");
29084 if (
SCC.getNode()) {
29091 SCC.getOperand(0),
SCC.getOperand(1),
29092 SCC.getOperand(4), Flags);
29093 AddToWorklist(
SETCC.getNode());
29094 return DAG.
getSelect(SDLoc(SCC),
SCC.getValueType(), SETCC,
29095 SCC.getOperand(2),
SCC.getOperand(3), Flags);
29108bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect,
SDValue LHS,
29118 const ConstantFPSDNode *
Zero =
nullptr;
29129 CmpLHS =
Cmp.getOperand(0);
29133 if (Zero &&
Zero->isZero() &&
29137 CombineTo(TheSelect, Sqrt);
29147 if (
LHS.getOpcode() !=
RHS.getOpcode() ||
29160 if (
LHS.getOperand(0) !=
RHS.getOperand(0) ||
29198 SmallPtrSet<const SDNode *, 32> Visited;
29204 Visited.
insert(TheSelect);
29268 MMOFlags &= ~MachineMemOperand::MOInvariant;
29270 MMOFlags &= ~MachineMemOperand::MODereferenceable;
29274 LLD->
getChain(), Addr, MachinePointerInfo(AddrSpace),
29275 Alignment, MMOFlags);
29282 MachinePointerInfo(AddrSpace), LLD->
getMemoryVT(), Alignment,
29287 CombineTo(TheSelect, Load);
29291 CombineTo(
LHS.getNode(),
Load.getValue(0),
Load.getValue(1));
29292 CombineTo(
RHS.getNode(),
Load.getValue(0),
Load.getValue(1));
29333 if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue() - 1)) == 0)) {
29334 unsigned ShCt = XType.
getSizeInBits() - N2C->getAPIntValue().logBase2() - 1;
29338 AddToWorklist(Shift.
getNode());
29340 if (XType.
bitsGT(AType)) {
29342 AddToWorklist(Shift.
getNode());
29346 Shift = DAG.
getNOT(
DL, Shift, AType);
29358 AddToWorklist(Shift.
getNode());
29360 if (XType.
bitsGT(AType)) {
29362 AddToWorklist(Shift.
getNode());
29366 Shift = DAG.
getNOT(
DL, Shift, AType);
29372SDValue DAGCombiner::foldSelectOfBinops(SDNode *
N) {
29426SDValue DAGCombiner::foldSignChangeInBitcast(SDNode *
N) {
29428 EVT VT =
N->getValueType(0);
29436 EVT IntVT =
Int.getValueType();
29450 SignMask = ~SignMask;
29456 SignMask = ~SignMask;
29461 AddToWorklist(
Int.getNode());
29469SDValue DAGCombiner::convertSelectOfFPConstantsToLoadOffset(
29485 TLI.
isFPImmLegal(TV->getValueAPF(), TV->getValueType(0), ForCodeSize) ||
29486 TLI.
isFPImmLegal(FV->getValueAPF(), FV->getValueType(0), ForCodeSize))
29491 if (!TV->hasOneUse() && !FV->hasOneUse())
29495 const_cast<ConstantFP*
>(TV->getConstantFPValue()) };
29512 AddToWorklist(
Cond.getNode());
29514 AddToWorklist(CstOffset.
getNode());
29516 AddToWorklist(CPIdx.
getNode());
29526 bool NotExtCompare) {
29528 if (N2 == N3)
return N2;
29539 AddToWorklist(
SCC.getNode());
29543 return !(SCCC->isZero()) ? N2 : N3;
29548 convertSelectOfFPConstantsToLoadOffset(
DL, N0, N1, N2, N3, CC))
29551 if (
SDValue V = foldSelectCCToShiftAnd(
DL, N0, N1, N2, N3, CC))
29564 if (ConstAndRHS && ConstAndRHS->getAPIntValue().popcount() == 1) {
29566 const APInt &AndMask = ConstAndRHS->getAPIntValue();
29584 bool Fold = N2C &&
isNullConstant(N3) && N2C->getAPIntValue().isPowerOf2();
29585 bool Swap = N3C &&
isNullConstant(N2) && N3C->getAPIntValue().isPowerOf2();
29587 if ((Fold || Swap) &&
29600 if (NotExtCompare && N2C->isOne())
29609 SCC = DAG.
getSetCC(SDLoc(N0), MVT::i1, N0, N1, CC);
29613 AddToWorklist(
SCC.getNode());
29614 AddToWorklist(Temp.
getNode());
29619 unsigned ShCt = N2C->getAPIntValue().logBase2();
29650 N0 ==
Count.getOperand(0) &&
29657 N0 ==
Count.getOperand(0) &&
29666 if (!NotExtCompare && N1C && N2C && N3C &&
29667 N2C->getAPIntValue() == ~N3C->getAPIntValue() &&
29680 if (CC ==
ISD::SETGT && N1C && N2C && N3C && N1C->isAllOnes() &&
29681 N2C->isOne() && N3C->isAllOnes() &&
29696 if (
SDValue ABD = foldSelectToABD(N0, N1, N2, N3, CC,
DL))
29725 const auto IsSrc = [&](
SDValue V) {
29736 while (!Worklist.
empty()) {
29738 if (!V.hasOneUse() && (Src && Src != V))
29741 if (V.getOpcode() ==
ISD::OR) {
29758 PartsMask |= (RootMask << ShiftAmtVal);
29763 PartsMask |= RootMask;
29781 bool foldBooleans) {
29782 TargetLowering::DAGCombinerInfo
29783 DagCombineInfo(DAG, Level,
false,
this);
29802SDValue DAGCombiner::BuildSDIV(SDNode *
N) {
29810 for (SDNode *
N : Built)
29820SDValue DAGCombiner::BuildSDIVPow2(SDNode *
N) {
29831 for (SDNode *
N : Built)
29843SDValue DAGCombiner::BuildUDIV(SDNode *
N) {
29851 for (SDNode *
N : Built)
29861SDValue DAGCombiner::BuildSREMPow2(SDNode *
N) {
29872 for (SDNode *
N : Built)
29892 bool AssumeNonZero) {
29895 auto PeekThroughCastsAndTrunc = [](
SDValue V) {
29897 switch (V.getOpcode()) {
29900 V = V.getOperand(0);
29911 Op = PeekThroughCastsAndTrunc(
Op);
29917 if (
C->isZero() ||
C->isOpaque())
29920 if (
C->getAPIntValue().isPowerOf2()) {
29937 for (
const APInt &Pow2 : Pow2Constants)
29946 auto CastToVT = [&](
EVT NewVT,
SDValue ToCast) {
29951 ToCast = ToCast.getOperand(0);
29952 EVT CurVT = ToCast.getValueType();
29953 if (NewVT == CurVT)
29965 if (AssumeNonZero ||
Op->getFlags().hasNoUnsignedWrap() ||
29968 Depth + 1, AssumeNonZero))
29970 CastToVT(VT,
Op.getOperand(1)));
29996 return DAG.
getNode(
Op.getOpcode(),
DL, VT, LogX, LogY);
30005 bool KnownNonZero,
bool InexpensiveOnly,
30006 std::optional<EVT> OutVT) {
30007 EVT VT = OutVT ? *OutVT :
V.getValueType();
30008 SDValue InexpensiveLogBase2 =
30011 return InexpensiveLogBase2;
30028 SDNodeFlags Flags) {
30033 EVT VT =
Op.getValueType();
30041 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
30048 AddToWorklist(Est.getNode());
30056 for (
int i = 0; i < Iterations; ++i) {
30059 if (i == Iterations - 1) {
30061 AddToWorklist(MulEst.
getNode());
30065 AddToWorklist(NewEst.
getNode());
30068 (i == Iterations - 1 ?
N : FPOne), NewEst, Flags);
30069 AddToWorklist(NewEst.
getNode());
30072 AddToWorklist(NewEst.
getNode());
30075 AddToWorklist(Est.getNode());
30080 AddToWorklist(Est.getNode());
30096 unsigned Iterations,
bool Reciprocal) {
30107 for (
unsigned i = 0; i < Iterations; ++i) {
30127 unsigned Iterations,
bool Reciprocal) {
30139 for (
unsigned i = 0; i < Iterations; ++i) {
30148 if (Reciprocal || (i + 1) < Iterations) {
30170 EVT VT =
Op.getValueType();
30178 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
30185 bool UseOneConstNR =
false;
30189 AddToWorklist(Est.
getNode());
30191 if (Iterations > 0)
30192 Est = UseOneConstNR
30193 ? buildSqrtNROneConst(
Op, Est, Iterations, Reciprocal)
30194 : buildSqrtNRTwoConst(
Op, Est, Iterations, Reciprocal);
30213 return buildSqrtEstimateImpl(
Op,
true);
30217 return buildSqrtEstimateImpl(
Op,
false);
30221bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1)
const {
30223 struct MemUseCharacteristics {
30228 LocationSize NumBytes;
30229 MachineMemOperand *MMO;
30232 auto getCharacteristics = [
this](SDNode *
N) -> MemUseCharacteristics {
30238 ? -1 *
C->getSExtValue()
30240 TypeSize
Size = LSN->getMemoryVT().getStoreSize();
30241 return {LSN->isVolatile(), LSN->isAtomic(),
30242 LSN->getBasePtr(),
Offset ,
30252 (MachineMemOperand *)
nullptr};
30260 (MachineMemOperand *)
nullptr};
30263 MemUseCharacteristics MUC0 = getCharacteristics(Op0),
30264 MUC1 = getCharacteristics(Op1);
30267 if (MUC0.BasePtr.getNode() && MUC0.BasePtr == MUC1.BasePtr &&
30268 MUC0.Offset == MUC1.Offset)
30272 if (MUC0.IsVolatile && MUC1.IsVolatile)
30277 if (MUC0.IsAtomic && MUC1.IsAtomic)
30280 if (MUC0.MMO && MUC1.MMO) {
30281 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
30282 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
30288 if ((MUC0.NumBytes.hasValue() && MUC0.NumBytes.isScalable() &&
30289 MUC0.Offset != 0) ||
30290 (MUC1.NumBytes.hasValue() && MUC1.NumBytes.isScalable() &&
30302 if (!MUC0.MMO || !MUC1.MMO)
30308 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
30309 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
30317 int64_t SrcValOffset0 = MUC0.MMO->getOffset();
30318 int64_t SrcValOffset1 = MUC1.MMO->getOffset();
30319 Align OrigAlignment0 = MUC0.MMO->getBaseAlign();
30320 Align OrigAlignment1 = MUC1.MMO->getBaseAlign();
30321 LocationSize Size0 = MUC0.NumBytes;
30322 LocationSize Size1 = MUC1.NumBytes;
30324 if (OrigAlignment0 == OrigAlignment1 && SrcValOffset0 != SrcValOffset1 &&
30330 int64_t OffAlign0 = SrcValOffset0 % OrigAlignment0.
value();
30331 int64_t OffAlign1 = SrcValOffset1 % OrigAlignment1.
value();
30335 if ((OffAlign0 +
static_cast<int64_t
>(
30337 (OffAlign1 +
static_cast<int64_t
>(
30351 if (
UseAA && BatchAA && MUC0.MMO->getValue() && MUC1.MMO->getValue() &&
30354 (!Size0.
isScalable() || SrcValOffset0 == 0) &&
30355 (!Size1.
isScalable() || SrcValOffset1 == 0)) {
30357 int64_t MinOffset = std::min(SrcValOffset0, SrcValOffset1);
30362 LocationSize Loc0 =
30364 LocationSize Loc1 =
30367 MemoryLocation(MUC0.MMO->getValue(), Loc0,
30368 UseTBAA ? MUC0.MMO->getAAInfo() : AAMDNodes()),
30369 MemoryLocation(MUC1.MMO->getValue(), Loc1,
30370 UseTBAA ? MUC1.MMO->getAAInfo() : AAMDNodes())))
30380void DAGCombiner::GatherAllAliases(SDNode *
N,
SDValue OriginalChain,
30381 SmallVectorImpl<SDValue> &Aliases) {
30383 SmallPtrSet<SDNode *, 16> Visited;
30391 unsigned Depth = 0;
30394 auto ImproveChain = [&](
SDValue &
C) ->
bool {
30395 switch (
C.getOpcode()) {
30406 if ((IsLoad && IsOpLoad) || !
mayAlias(
N,
C.getNode())) {
30408 C =
C.getOperand(0);
30417 C =
C.getOperand(0);
30426 C =
C.getOperand(0);
30439 while (!Chains.
empty()) {
30473 if (ImproveChain(Chain)) {
30495 GatherAllAliases(
N, OldChain, Aliases);
30498 if (Aliases.
empty())
30502 if (Aliases.
size() == 1)
30522bool DAGCombiner::parallelizeChainedStores(StoreSDNode *St) {
30524 StoreSDNode *STChain = St;
30529 using IMap = llvm::IntervalMap<int64_t, std::monostate, 8,
30530 IntervalMapHalfOpenInfo<int64_t>>;
30539 if (!
BasePtr.getBase().getNode())
30543 if (
BasePtr.getBase().isUndef())
30561 if (Chain->getMemoryVT().isScalableVector())
30565 if (!
SDValue(Chain, 0)->hasOneUse())
30568 if (!Chain->isSimple() || Chain->isIndexed())
30577 int64_t
Length = (Chain->getMemoryVT().getSizeInBits() + 7) / 8;
30585 if (
I != Intervals.begin() && (--
I).stop() <=
Offset)
30594 if (ChainedStores.
empty())
30601 for (
unsigned I = ChainedStores.
size();
I;) {
30602 StoreSDNode *S = ChainedStores[--
I];
30603 SDValue BetterChain = FindBetterChain(S, NewChain);
30607 ChainedStores[
I] = S;
30611 SDValue BetterChain = FindBetterChain(St, NewChain);
30626 auto hasImprovedChain = [&](
SDValue ST) ->
bool {
30627 return ST->getOperand(0) != NewChain;
30629 bool AddNewChain =
llvm::all_of(TFOps, hasImprovedChain);
30639 AddToWorklist(
Op.getNode());
30640 AddToWorklist(STChain);
30644bool DAGCombiner::findBetterNeighborChains(StoreSDNode *St) {
30651 if (!
BasePtr.getBase().getNode())
30655 if (
BasePtr.getBase().isUndef())
30659 if (parallelizeChainedStores(St))
30664 if (St->
getChain() != BetterChain) {
30665 replaceStoreChain(St, BetterChain);
30675 DAGCombiner(*
this, BatchAA, OptLevel).Run(Level);
static bool mayAlias(MachineInstr &MIa, SmallVectorImpl< MachineInstr * > &MemInsns, AliasAnalysis *AA)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< bool > UseAA("aarch64-use-aa", cl::init(true), cl::desc("Enable the use of AA during codegen."))
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
AMDGPU Register Bank Select
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool splitMergedValStore(StoreInst &SI, const DataLayout &DL, const TargetLowering &TLI)
For the instruction sequence of store below, F and I values are bundled together as an i64 value befo...
static unsigned bigEndianByteAt(const unsigned ByteWidth, const unsigned I)
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
static bool canFoldInAddressingMode(GLoadStore *MI, const TargetLowering &TLI, MachineRegisterInfo &MRI)
Return true if 'MI' is a load or a store that may be fold it's address operand into the load / store ...
static unsigned littleEndianByteAt(const unsigned ByteWidth, const unsigned I)
static bool isAnyConstantBuildVector(SDValue V, bool NoOpaques=false)
static cl::opt< bool > EnableShrinkLoadReplaceStoreWithStore("combiner-shrink-load-replace-store-with-store", cl::Hidden, cl::init(true), cl::desc("DAG combiner enable load/<replace bytes>/store with " "a narrower store"))
static bool ExtendUsesToFormExtLoad(EVT VT, SDNode *N, SDValue N0, unsigned ExtOpc, SmallVectorImpl< SDNode * > &ExtendNodes, const TargetLowering &TLI)
static cl::opt< unsigned > TokenFactorInlineLimit("combiner-tokenfactor-inline-limit", cl::Hidden, cl::init(2048), cl::desc("Limit the number of operands to inline for Token Factors"))
static SDValue tryToFoldExtOfLoad(SelectionDAG &DAG, DAGCombiner &Combiner, const TargetLowering &TLI, EVT VT, bool LegalOperations, SDNode *N, SDValue N0, ISD::LoadExtType ExtLoadType, ISD::NodeType ExtOpc, bool NonNegZExt=false)
static SDValue ConvertSelectToConcatVector(SDNode *N, SelectionDAG &DAG)
static SDNode * getBuildPairElt(SDNode *N, unsigned i)
static SDValue foldExtractSubvectorFromShuffleVector(EVT NarrowVT, SDValue Src, unsigned Index, const SDLoc &DL, SelectionDAG &DAG, bool LegalOperations)
Given EXTRACT_SUBVECTOR(VECTOR_SHUFFLE(Op0, Op1, Mask)), try to produce VECTOR_SHUFFLE(EXTRACT_SUBVEC...
static SDValue foldToMaskedStore(StoreSDNode *Store, SelectionDAG &DAG, const SDLoc &Dl)
static SDValue foldBitOrderCrossLogicOp(SDNode *N, SelectionDAG &DAG)
static SDValue tryToFoldExtendOfConstant(SDNode *N, const SDLoc &DL, const TargetLowering &TLI, SelectionDAG &DAG, bool LegalTypes)
Try to fold a sext/zext/aext dag node into a ConstantSDNode or a build_vector of constants.
static unsigned getMinMaxOpcodeForClamp(bool IsMin, SDValue Operand1, SDValue Operand2, SelectionDAG &DAG, const TargetLowering &TLI)
Returns an appropriate FP min/max opcode for clamping operations.
static SDValue extractShiftForRotate(SelectionDAG &DAG, SDValue OppShift, SDValue ExtractFrom, SDValue &Mask, const SDLoc &DL)
Helper function for visitOR to extract the needed side of a rotate idiom from a shl/srl/mul/udiv.
static bool getCombineLoadStoreParts(SDNode *N, unsigned Inc, unsigned Dec, bool &IsLoad, bool &IsMasked, SDValue &Ptr, const TargetLowering &TLI)
bool refineUniformBase(SDValue &BasePtr, SDValue &Index, bool IndexIsScaled, SelectionDAG &DAG, const SDLoc &DL)
static SDValue narrowExtractedVectorLoad(EVT VT, SDValue Src, unsigned Index, const SDLoc &DL, SelectionDAG &DAG)
If we are extracting a subvector from a wide vector load, convert to a narrow load to eliminate the e...
static SDValue scalarizeExtractedBinOp(SDNode *ExtElt, SelectionDAG &DAG, const SDLoc &DL, bool LegalTypes)
Transform a vector binary operation into a scalar binary operation by moving the math/logic after an ...
static 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 unsigned getMinMaxOpcodeForCompareFold(SDValue Operand1, SDValue Operand2, ISD::CondCode CC, unsigned OrAndOpcode, SelectionDAG &DAG, bool isFMAXNUMFMINNUM_IEEE, bool isFMAXNUMFMINNUM)
static bool shouldConvertSelectOfConstantsToMath(const SDValue &Cond, EVT VT, const TargetLowering &TLI)
static cl::opt< bool > EnableStoreMerging("combiner-store-merging", cl::Hidden, cl::init(true), cl::desc("DAG combiner enable merging multiple stores " "into a wider store"))
static bool isContractableFMUL(const TargetOptions &Options, SDValue N)
static cl::opt< bool > MaySplitLoadIndex("combiner-split-load-index", cl::Hidden, cl::init(true), cl::desc("DAG combiner may split indexing from loads"))
static bool areSlicesNextToEachOther(const LoadedSlice &First, const LoadedSlice &Second)
Check whether or not First and Second are next to each other in memory.
static SDValue stripConstantMask(const SelectionDAG &DAG, SDValue Op, SDValue &Mask)
static bool arebothOperandsNotSNan(SDValue Operand1, SDValue Operand2, SelectionDAG &DAG)
static bool isBSwapHWordPair(SDValue N, MutableArrayRef< SDNode * > Parts)
static SDValue foldFPToIntToFP(SDNode *N, const SDLoc &DL, SelectionDAG &DAG, const TargetLowering &TLI)
static bool CanCombineFCOPYSIGN_EXTEND_ROUND(EVT XTy, EVT YTy)
copysign(x, fp_extend(y)) -> copysign(x, y) copysign(x, fp_round(y)) -> copysign(x,...
static cl::opt< bool > ReduceLoadOpStoreWidthForceNarrowingProfitable("combiner-reduce-load-op-store-width-force-narrowing-profitable", cl::Hidden, cl::init(false), cl::desc("DAG combiner force override the narrowing profitable check when " "reducing the width of load/op/store sequences"))
static SDValue getTruncatedUSUBSAT(EVT DstVT, EVT SrcVT, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
static SDValue foldToSaturated(SDNode *N, EVT &VT, SDValue &Src, EVT &SrcVT, SDLoc &DL, const TargetLowering &TLI, SelectionDAG &DAG)
static SDValue FoldIntToFPToInt(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
static SDValue foldSubCtlzNot(SDNode *N, SelectionDAG &DAG)
static SDNode * getPostIndexedLoadStoreOp(SDNode *N, bool &IsLoad, bool &IsMasked, SDValue &Ptr, SDValue &BasePtr, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG, const TargetLowering &TLI)
static SDValue extractBooleanFlip(SDValue V, SelectionDAG &DAG, const TargetLowering &TLI, bool Force)
Flips a boolean if it is cheaper to compute.
static bool isTruncateOf(SelectionDAG &DAG, SDValue N, SDValue &Op, KnownBits &Known)
static SDValue tryToFoldExtOfMaskedLoad(SelectionDAG &DAG, const TargetLowering &TLI, EVT VT, bool LegalOperations, SDNode *N, SDValue N0, ISD::LoadExtType ExtLoadType, ISD::NodeType ExtOpc)
static SDValue 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 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 constexpr roundingMode rmTowardZero
static LLVM_ABI ExponentType semanticsMinExponent(const fltSemantics &)
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI ExponentType semanticsMaxExponent(const fltSemantics &)
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
static LLVM_ABI bool isIEEELikeFP(const fltSemantics &)
opStatus
IEEE-754R 7: Default exception handling.
static LLVM_ABI unsigned int semanticsIntSizeInBits(const fltSemantics &, bool)
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
opStatus divide(const APFloat &RHS, roundingMode RM)
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
const fltSemantics & getSemantics() const
APFloat makeQuiet() const
Assuming this is an IEEE-754 NaN value, quiet its signaling bit.
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
APInt bitcastToAPInt() const
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
LLVM_ABI APInt umul_ov(const APInt &RHS, bool &Overflow) const
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
static LLVM_ABI void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
Dual division/remainder interface.
LLVM_ABI APInt getLoBits(unsigned numBits) const
Compute an APInt containing numBits lowbits from this APInt.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
void setBitsFrom(unsigned loBit)
Set the top bits starting from loBit.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
APInt abs() const
Get the absolute value.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
bool isNegative() const
Determine sign of this APInt.
bool intersects(const APInt &RHS) const
This operation tests if there are any pairs of corresponding bits between this APInt and RHS that are...
int32_t exactLogBase2() const
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 isMaxSignedValue() const
Determine if this is the largest signed value.
bool ule(const APInt &RHS) const
Unsigned less or equal comparison.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
void setBits(unsigned loBit, unsigned hiBit)
Set the bits from loBit (inclusive) to hiBit (exclusive) to 1.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
LLVM_ABI APInt extractBits(unsigned numBits, unsigned bitPosition) const
Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
bool isOne() const
Determine if this is a value of 1.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
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(CounterInfo &Counter)
iterator find(const_arg_type_t< KeyT > Val)
static constexpr ElementCount getFixed(ScalarTy MinVal)
constexpr bool isScalar() const
Exactly one element.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
AttributeList getAttributes() const
Return the attribute list for this Function.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const_iterator find(KeyT x) const
find - Return an iterator pointing to the first interval ending at or after x, or end().
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 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 SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
LLVM_ABI void Combine(CombineLevel Level, BatchAAResults *BatchAA, CodeGenOptLevel OptLevel)
This iterates over the nodes in the SelectionDAG, folding certain types of nodes together,...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
static LLVM_ABI unsigned getHasPredecessorMaxSteps()
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI bool cannotBeOrderedNegativeFP(SDValue Op) const
Test whether the given float value is known to be positive.
LLVM_ABI SDValue getGetFPEnv(SDValue Chain, const SDLoc &dl, SDValue Ptr, EVT MemVT, MachineMemOperand *MMO)
LLVM_ABI SDValue getAssertAlign(const SDLoc &DL, SDValue V, Align A)
Return an AssertAlignSDNode.
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI bool canIgnoreSignBitOfZero(const SDUse &Use) const
Check if a use of a float value is insensitive to signed zeros.
LLVM_ABI bool SignBitIsZeroFP(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero, for a floating-point value.
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
LLVM_ABI SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal)
Returns a vector of type ResVT whose elements contain the linear sequence <0, Step,...
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...
EVT getLegalTypeToTransformTo(LLVMContext &Context, EVT VT) const
Perform getTypeToTransformTo repeatedly until a legal type is obtained.
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 ...
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Get the libcall impl routine name for the specified libcall.
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.
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.
@ PTRADD
PTRADD represents pointer arithmetic semantics, for targets that opt in using shouldPreservePtrArith(...
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ POISON
POISON - A poison node.
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ SMULFIX
RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on 2 integers with the same...
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADDC
Carry-setting nodes for multiple precision addition and subtraction.
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SMULFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ FMULADD
FMULADD - Performs a * b + c, with, or without, intermediate rounding.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ 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 ...
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor to...
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ AssertAlign
AssertAlign - These nodes record if a register contains a value that has a known alignment and the tr...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EntryToken
EntryToken - This is the marker used to indicate the start of a region.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ VSCALE
VSCALE(IMM) - Returns the runtime scaling factor used to calculate the number of elements within a sc...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
@ SMULO
Same for multiplication.
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ LIFETIME_START
This corresponds to the llvm.lifetime.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ MGATHER
Masked gather and scatter - load and store operations for a vector of random addresses with additiona...
@ HANDLENODE
HANDLENODE node - Used as a handle for various purposes.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ TargetConstant
TargetConstant* - Like Constant*, but the DAG does not do any folding, simplification,...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ GET_FPENV_MEM
Gets the current floating-point environment.
@ CARRY_FALSE
CARRY_FALSE - This node is used when folding other nodes, like ADDC/SUBC, which indicate the carry re...
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ ADDE
Carry-using nodes for multiple precision addition and subtraction.
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ EXPERIMENTAL_VECTOR_HISTOGRAM
Experimental vector histogram intrinsic Operands: Input Chain, Inc, Mask, Base, Index,...
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ BRCOND
BRCOND - Conditional branch.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ CALLSEQ_START
CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end of a call sequence,...
@ SET_FPENV_MEM
Sets the current floating point environment.
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ TRUNCATE_SSAT_S
TRUNCATE_[SU]SAT_[SU] - Truncate for saturated operand [SU] located in middle, prefix for SAT means i...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ SADDO_CARRY
Carry-using overflow-aware nodes for multiple precision addition and subtraction.
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isIndexTypeSigned(MemIndexType IndexType)
bool isExtVecInRegOpcode(unsigned Opcode)
LLVM_ABI 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)
ReassociatableOpc_match< PatternTs... > m_ReassociatableAdd(const PatternTs &...Patterns)
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.
ReassociatableOpc_match< PatternTs... > m_ReassociatableAnd(const PatternTs &...Patterns)
NUses_match< 1, Value_match > m_OneUse()
CondCode_match m_CondCode()
Match any conditional code SDNode.
Not(const Pred &P) -> Not< Pred >
TernaryOpc_match< T0_P, T1_P, T2_P, true, false > m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC)
bool sd_context_match(SDValue N, const MatchContext &Ctx, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
@ User
could "use" a pointer
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
bool operator<(int64_t V1, const APSInt &V2)
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
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)
LLVM_ABI bool isOneOrOneSplatFP(SDValue V, bool AllowUndefs=false)
Return true if the value is a constant floating-point value, or a splatted vector of a constant float...
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr 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 isZeroOrZeroSplat(SDValue N, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
LLVM_ABI void getShuffleMaskWithWidestElts(ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Repetitively apply widenShuffleMaskElts() for as long as it succeeds, to get the shuffle mask with wi...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
LLVM_ABI bool isNullFPConstant(SDValue V)
Returns true if V is an FP constant with a value of positive zero.
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI bool isZeroOrZeroSplatFP(SDValue N, bool AllowUndefs=false)
Return true if the value is a constant (+/-)0.0 floating-point value or a splatted vector thereof (wi...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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...