84#define DEBUG_TYPE "dagcombine"
86STATISTIC(NodesCombined ,
"Number of dag nodes combined");
87STATISTIC(PreIndexedNodes ,
"Number of pre-indexed nodes created");
88STATISTIC(PostIndexedNodes,
"Number of post-indexed nodes created");
89STATISTIC(OpsNarrowed ,
"Number of load/op/store narrowed");
90STATISTIC(LdStFP2Int ,
"Number of fp load/store pairs transformed to int");
92STATISTIC(NumFPLogicOpsConv,
"Number of logic ops converted to fp ops");
95 "Controls whether a DAG combine is performed for a node");
99 cl::desc(
"Enable DAG combiner's use of IR alias analysis"));
103 cl::desc(
"Enable DAG combiner's use of TBAA"));
108 cl::desc(
"Only use DAG-combiner alias analysis in this"
116 cl::desc(
"Bypass the profitability model of load slicing"),
121 cl::desc(
"DAG combiner may split indexing from loads"));
125 cl::desc(
"DAG combiner enable merging multiple stores "
126 "into a wider store"));
130 cl::desc(
"Limit the number of operands to inline for Token Factors"));
134 cl::desc(
"Limit the number of times for the same StoreNode and RootNode "
135 "to bail out in store merging dependence check"));
139 cl::desc(
"DAG combiner enable reducing the width of load/op/store "
142 "combiner-reduce-load-op-store-width-force-narrowing-profitable",
144 cl::desc(
"DAG combiner force override the narrowing profitable check when "
145 "reducing the width of load/op/store sequences"));
149 cl::desc(
"DAG combiner enable load/<replace bytes>/store with "
150 "a narrower store"));
155 "Enable merging extends and rounds into FCOPYSIGN on vector types"));
164 bool LegalDAG =
false;
165 bool LegalOperations =
false;
166 bool LegalTypes =
false;
168 bool DisableGenericCombines;
204 void AddUsersToWorklist(
SDNode *
N) {
210 void AddToWorklistWithUsers(
SDNode *
N) {
211 AddUsersToWorklist(
N);
218 void clearAddedDanglingWorklistEntries() {
220 while (!PruningList.
empty()) {
223 recursivelyDeleteUnusedNodes(
N);
227 SDNode *getNextWorklistEntry() {
229 clearAddedDanglingWorklistEntries();
233 while (!
N && !Worklist.
empty()) {
238 assert(
N->getCombinerWorklistIndex() >= 0 &&
239 "Found a worklist entry without a corresponding map entry!");
241 N->setCombinerWorklistIndex(-2);
251 : DAG(
D), TLI(
D.getTargetLoweringInfo()),
252 STI(
D.getSubtarget().getSelectionDAGInfo()), OptLevel(OL),
257 MaximumLegalStoreInBits = 0;
263 VT.getSizeInBits().getKnownMinValue() >= MaximumLegalStoreInBits)
264 MaximumLegalStoreInBits = VT.getSizeInBits().getKnownMinValue();
267 void ConsiderForPruning(
SDNode *
N) {
274 void AddToWorklist(
SDNode *
N,
bool IsCandidateForPruning =
true,
275 bool SkipIfCombinedBefore =
false) {
277 "Deleted Node added to Worklist");
284 if (SkipIfCombinedBefore &&
N->getCombinerWorklistIndex() == -2)
287 if (IsCandidateForPruning)
288 ConsiderForPruning(
N);
290 if (
N->getCombinerWorklistIndex() < 0) {
291 N->setCombinerWorklistIndex(Worklist.
size());
297 void removeFromWorklist(
SDNode *
N) {
299 StoreRootCountMap.
erase(
N);
301 int WorklistIndex =
N->getCombinerWorklistIndex();
305 if (WorklistIndex < 0)
309 Worklist[WorklistIndex] =
nullptr;
310 N->setCombinerWorklistIndex(-1);
313 void deleteAndRecombine(
SDNode *
N);
314 bool recursivelyDeleteUnusedNodes(
SDNode *
N);
322 return CombineTo(
N, &Res, 1, AddTo);
329 return CombineTo(
N, To, 2, AddTo);
335 unsigned MaximumLegalStoreInBits;
341 unsigned BitWidth =
Op.getScalarValueSizeInBits();
347 EVT VT =
Op.getValueType();
351 return SimplifyDemandedBits(
Op,
DemandedBits, DemandedElts,
false);
357 bool SimplifyDemandedVectorElts(
SDValue Op) {
359 if (
Op.getValueType().isScalableVector())
362 unsigned NumElts =
Op.getValueType().getVectorNumElements();
364 return SimplifyDemandedVectorElts(
Op, DemandedElts);
368 const APInt &DemandedElts,
369 bool AssumeSingleUse =
false);
370 bool SimplifyDemandedVectorElts(
SDValue Op,
const APInt &DemandedElts,
371 bool AssumeSingleUse =
false);
373 bool CombineToPreIndexedLoadStore(
SDNode *
N);
374 bool CombineToPostIndexedLoadStore(
SDNode *
N);
399 void ReplaceLoadWithPromotedLoad(
SDNode *Load,
SDNode *ExtLoad);
540 bool refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
SDNode *
N);
572 template <
class MatchContextClass>
574 template <
class MatchContextClass>
579 bool reassociationCanBreakAddressingModePattern(
unsigned Opc,
588 SDValue reassociateReduction(
unsigned RedOpc,
unsigned Opc,
const SDLoc &
DL,
602 bool NotExtCompare =
false);
603 SDValue convertSelectOfFPConstantsToLoadOffset(
620 const SDLoc &
DL,
bool foldBooleans);
624 SDValue &
CC,
bool MatchStrict =
false)
const;
625 bool isOneUseSetCC(
SDValue N)
const;
650 bool KnownNeverZero =
false,
651 bool InexpensiveOnly =
false,
652 std::optional<EVT> OutVT = std::nullopt);
662 bool DemandHighBits =
true);
666 unsigned PosOpcode,
unsigned NegOpcode,
670 unsigned PosOpcode,
unsigned NegOpcode,
686 SDValue VecIn2,
unsigned LeftIdx,
721 int64_t OffsetFromBase;
724 : MemNode(
N), OffsetFromBase(
Offset) {}
729 StoreSource getStoreSource(
SDValue StoreVal) {
733 return StoreSource::Constant;
737 return StoreSource::Constant;
738 return StoreSource::Unknown;
741 return StoreSource::Extract;
743 return StoreSource::Load;
745 return StoreSource::Unknown;
753 bool isMulAddWithConstProfitable(
SDNode *MulNode,
SDValue AddNode,
760 EVT LoadResultTy,
EVT &ExtVT);
765 EVT &MemVT,
unsigned ShAmt = 0);
773 bool BackwardsPropagateMask(
SDNode *
N);
790 EVT MemVT,
unsigned NumStores,
791 bool IsConstantSrc,
bool UseVector,
804 bool checkMergeStoreCandidatesForDependencies(
812 int64_t ElementSizeBytes)
const;
817 unsigned NumConsecutiveStores,
818 EVT MemVT,
SDNode *Root,
bool AllowVectors);
825 unsigned NumConsecutiveStores,
EVT MemVT,
831 unsigned NumConsecutiveStores,
EVT MemVT,
832 SDNode *Root,
bool AllowVectors,
833 bool IsNonTemporalStore,
bool IsNonTemporalLoad);
852 bool hasOperation(
unsigned Opcode,
EVT VT) {
863 EVT getShiftAmountTy(
EVT LHSTy) {
869 bool isTypeLegal(
const EVT &VT) {
870 if (!LegalTypes)
return true;
875 EVT getSetCCResultType(
EVT VT)
const {
890 explicit WorklistRemover(DAGCombiner &dc)
891 :
SelectionDAG::DAGUpdateListener(dc.getDAG()), DC(dc) {}
894 DC.removeFromWorklist(
N);
902 explicit WorklistInserter(DAGCombiner &dc)
903 :
SelectionDAG::DAGUpdateListener(dc.getDAG()), DC(dc) {}
917 ((DAGCombiner*)
DC)->AddToWorklist(
N);
922 return ((DAGCombiner*)DC)->CombineTo(
N, &To[0], To.
size(), AddTo);
927 return ((DAGCombiner*)DC)->CombineTo(
N, Res, AddTo);
932 return ((DAGCombiner*)DC)->CombineTo(
N, Res0, Res1, AddTo);
937 return ((DAGCombiner*)DC)->recursivelyDeleteUnusedNodes(
N);
942 return ((DAGCombiner*)DC)->CommitTargetLoweringOpt(TLO);
949void DAGCombiner::deleteAndRecombine(
SDNode *
N) {
950 removeFromWorklist(
N);
958 if (
Op->hasOneUse() ||
Op->getNumValues() > 1)
959 AddToWorklist(
Op.getNode());
968 unsigned Bits =
Offset + std::max(
LHS.getBitWidth(),
RHS.getBitWidth());
981 LHS =
N.getOperand(0);
982 RHS =
N.getOperand(1);
983 CC =
N.getOperand(2);
990 LHS =
N.getOperand(1);
991 RHS =
N.getOperand(2);
992 CC =
N.getOperand(3);
1004 LHS =
N.getOperand(0);
1005 RHS =
N.getOperand(1);
1006 CC =
N.getOperand(4);
1013bool DAGCombiner::isOneUseSetCC(
SDValue N)
const {
1015 if (isSetCCEquivalent(
N, N0, N1, N2) &&
N->hasOneUse())
1027 MaskForTy = 0xFFULL;
1030 MaskForTy = 0xFFFFULL;
1033 MaskForTy = 0xFFFFFFFFULL;
1052 return !(Const->isOpaque() && NoOpaques);
1055 unsigned BitWidth =
N.getScalarValueSizeInBits();
1060 if (!Const || Const->getAPIntValue().getBitWidth() !=
BitWidth ||
1061 (Const->isOpaque() && NoOpaques))
1080 !cast<ConstantSDNode>(LD->getOperand(2))->isOpaque());
1083bool DAGCombiner::reassociationCanBreakAddressingModePattern(
unsigned Opc,
1116 ScalableOffset = -ScalableOffset;
1118 if (
auto *LoadStore = dyn_cast<MemSDNode>(
Node);
1124 unsigned AS =
LoadStore->getAddressSpace();
1137 auto *C2 = dyn_cast<ConstantSDNode>(N1);
1141 const APInt &C2APIntVal = C2->getAPIntValue();
1145 if (
auto *C1 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) {
1149 const APInt &C1APIntVal = C1->getAPIntValue();
1150 const APInt CombinedValueIntVal = C1APIntVal + C2APIntVal;
1153 const int64_t CombinedValue = CombinedValueIntVal.
getSExtValue();
1156 if (
auto *LoadStore = dyn_cast<MemSDNode>(
Node)) {
1162 AM.
BaseOffs = C2APIntVal.getSExtValue();
1164 unsigned AS =
LoadStore->getAddressSpace();
1176 if (
auto *GA = dyn_cast<GlobalAddressSDNode>(N0.
getOperand(1)))
1189 AM.
BaseOffs = C2APIntVal.getSExtValue();
1191 unsigned AS =
LoadStore->getAddressSpace();
1204SDValue DAGCombiner::reassociateOpsCommutative(
unsigned Opc,
const SDLoc &
DL,
1218 Flags.hasNoUnsignedWrap())
1226 return DAG.
getNode(Opc,
DL, VT, N00, OpNode, NewFlags);
1234 return DAG.
getNode(Opc,
DL, VT, OpNode, N01, NewFlags);
1244 if (N1 == N00 || N1 == N01)
1290 if (CC1 == CC00 && CC1 != CC01) {
1292 return DAG.
getNode(Opc,
DL, VT, OpNode, N01, Flags);
1294 if (CC1 == CC01 && CC1 != CC00) {
1296 return DAG.
getNode(Opc,
DL, VT, OpNode, N00, Flags);
1314 if (!
Flags.hasAllowReassociation() || !
Flags.hasNoSignedZeros())
1317 if (
SDValue Combined = reassociateOpsCommutative(Opc,
DL, N0, N1, Flags))
1319 if (
SDValue Combined = reassociateOpsCommutative(Opc,
DL, N1, N0, Flags))
1327SDValue DAGCombiner::reassociateReduction(
unsigned RedOpc,
unsigned Opc,
1345 assert(
N->getNumValues() == NumTo &&
"Broken CombineTo call!");
1349 dbgs() <<
" and " << NumTo - 1 <<
" other values\n");
1350 for (
unsigned i = 0, e = NumTo; i !=
e; ++i)
1352 N->getValueType(i) == To[i].getValueType()) &&
1353 "Cannot combine value to value of different type!");
1355 WorklistRemover DeadNodes(*
this);
1359 for (
unsigned i = 0, e = NumTo; i !=
e; ++i) {
1361 AddToWorklistWithUsers(To[i].
getNode());
1369 deleteAndRecombine(
N);
1387 recursivelyDeleteUnusedNodes(TLO.
Old.
getNode());
1393 const APInt &DemandedElts,
1394 bool AssumeSingleUse) {
1402 AddToWorklist(
Op.getNode());
1404 CommitTargetLoweringOpt(TLO);
1411bool DAGCombiner::SimplifyDemandedVectorElts(
SDValue Op,
1412 const APInt &DemandedElts,
1413 bool AssumeSingleUse) {
1415 APInt KnownUndef, KnownZero;
1417 TLO, 0, AssumeSingleUse))
1421 AddToWorklist(
Op.getNode());
1423 CommitTargetLoweringOpt(TLO);
1427void DAGCombiner::ReplaceLoadWithPromotedLoad(
SDNode *Load,
SDNode *ExtLoad) {
1429 EVT VT =
Load->getValueType(0);
1438 AddToWorklist(Trunc.
getNode());
1439 recursivelyDeleteUnusedNodes(Load);
1447 EVT MemVT =
LD->getMemoryVT();
1449 :
LD->getExtensionType();
1452 LD->getChain(),
LD->getBasePtr(),
1453 MemVT,
LD->getMemOperand());
1456 unsigned Opc =
Op.getOpcode();
1460 if (
SDValue Op0 = SExtPromoteOperand(
Op.getOperand(0), PVT))
1464 if (
SDValue Op0 = ZExtPromoteOperand(
Op.getOperand(0), PVT))
1482 EVT OldVT =
Op.getValueType();
1484 bool Replace =
false;
1485 SDValue NewOp = PromoteOperand(
Op, PVT, Replace);
1488 AddToWorklist(NewOp.
getNode());
1491 ReplaceLoadWithPromotedLoad(
Op.getNode(), NewOp.
getNode());
1497 EVT OldVT =
Op.getValueType();
1499 bool Replace =
false;
1500 SDValue NewOp = PromoteOperand(
Op, PVT, Replace);
1503 AddToWorklist(NewOp.
getNode());
1506 ReplaceLoadWithPromotedLoad(
Op.getNode(), NewOp.
getNode());
1514 if (!LegalOperations)
1517 EVT VT =
Op.getValueType();
1523 unsigned Opc =
Op.getOpcode();
1531 assert(PVT != VT &&
"Don't know what type to promote to!");
1535 bool Replace0 =
false;
1537 SDValue NN0 = PromoteOperand(N0, PVT, Replace0);
1539 bool Replace1 =
false;
1541 SDValue NN1 = PromoteOperand(N1, PVT, Replace1);
1553 Replace1 &= (N0 != N1) && !N1->
hasOneUse();
1556 CombineTo(
Op.getNode(), RV);
1582 if (!LegalOperations)
1585 EVT VT =
Op.getValueType();
1591 unsigned Opc =
Op.getOpcode();
1599 assert(PVT != VT &&
"Don't know what type to promote to!");
1603 bool Replace =
false;
1606 N0 = SExtPromoteOperand(N0, PVT);
1608 N0 = ZExtPromoteOperand(N0, PVT);
1610 N0 = PromoteOperand(N0, PVT, Replace);
1621 ReplaceLoadWithPromotedLoad(
Op.getOperand(0).getNode(), N0.
getNode());
1631 if (!LegalOperations)
1634 EVT VT =
Op.getValueType();
1640 unsigned Opc =
Op.getOpcode();
1648 assert(PVT != VT &&
"Don't know what type to promote to!");
1658bool DAGCombiner::PromoteLoad(
SDValue Op) {
1659 if (!LegalOperations)
1665 EVT VT =
Op.getValueType();
1671 unsigned Opc =
Op.getOpcode();
1679 assert(PVT != VT &&
"Don't know what type to promote to!");
1684 EVT MemVT =
LD->getMemoryVT();
1686 :
LD->getExtensionType();
1688 LD->getChain(),
LD->getBasePtr(),
1689 MemVT,
LD->getMemOperand());
1698 AddToWorklist(
Result.getNode());
1699 recursivelyDeleteUnusedNodes(
N);
1712bool DAGCombiner::recursivelyDeleteUnusedNodes(
SDNode *
N) {
1713 if (!
N->use_empty())
1723 if (
N->use_empty()) {
1724 for (
const SDValue &ChildN :
N->op_values())
1725 Nodes.
insert(ChildN.getNode());
1727 removeFromWorklist(
N);
1732 }
while (!Nodes.
empty());
1747 WorklistInserter AddNodes(*
this);
1756 AddToWorklist(&
Node,
Node.use_empty());
1764 while (
SDNode *
N = getNextWorklistEntry()) {
1768 if (recursivelyDeleteUnusedNodes(
N))
1771 WorklistRemover DeadNodes(*
this);
1779 for (
SDNode *LN : UpdatedNodes)
1780 AddToWorklistWithUsers(LN);
1792 for (
const SDValue &ChildN :
N->op_values())
1793 AddToWorklist(ChildN.getNode(),
true,
1804 ChainsWithoutMergeableStores.
clear();
1815 "Node was deleted but visit returned new node!");
1823 N->getNumValues() == 1 &&
"Type mismatch");
1833 AddToWorklistWithUsers(RV.
getNode());
1839 recursivelyDeleteUnusedNodes(
N);
1849 switch (
N->getOpcode()) {
1875 case ISD::MUL:
return visitMUL<EmptyMatchContext>(
N);
1939 case ISD::FMA:
return visitFMA<EmptyMatchContext>(
N);
2011#define BEGIN_REGISTER_VP_SDNODE(SDOPC, ...) case ISD::SDOPC:
2012#include "llvm/IR/VPIntrinsics.def"
2013 return visitVPOp(
N);
2024 if (!DisableGenericCombines)
2030 "Node was deleted but visit returned NULL!");
2037 DagCombineInfo(DAG, Level,
false,
this);
2045 switch (
N->getOpcode()) {
2053 RV = PromoteIntBinOp(
SDValue(
N, 0));
2058 RV = PromoteIntShiftOp(
SDValue(
N, 0));
2079 if (N0 != N1 && (isa<ConstantSDNode>(N0) || !isa<ConstantSDNode>(N1))) {
2094 if (
unsigned NumOps =
N->getNumOperands()) {
2095 if (
N->getOperand(0).getValueType() == MVT::Other)
2096 return N->getOperand(0);
2097 if (
N->getOperand(NumOps-1).getValueType() == MVT::Other)
2098 return N->getOperand(NumOps-1);
2099 for (
unsigned i = 1; i < NumOps-1; ++i)
2100 if (
N->getOperand(i).getValueType() == MVT::Other)
2101 return N->getOperand(i);
2107 SDValue Operand =
N->getOperand(0);
2122 if (
N->getNumOperands() == 2) {
2124 return N->getOperand(0);
2126 return N->getOperand(1);
2141 AddToWorklist(*(
N->user_begin()));
2146 bool Changed =
false;
2153 for (
unsigned i = 0; i < TFs.
size(); ++i) {
2158 for (
unsigned j = i;
j < TFs.
size();
j++)
2169 switch (
Op.getOpcode()) {
2187 if (SeenOps.
insert(
Op.getNode()).second)
2198 for (
unsigned i = 1, e = TFs.
size(); i < e; i++)
2199 AddToWorklist(TFs[i]);
2211 bool DidPruneOps =
false;
2213 unsigned NumLeftToConsider = 0;
2215 Worklist.
push_back(std::make_pair(
Op.getNode(), NumLeftToConsider++));
2219 auto AddToWorklist = [&](
unsigned CurIdx,
SDNode *
Op,
unsigned OpNumber) {
2225 unsigned OrigOpNumber = 0;
2226 while (OrigOpNumber < Ops.size() && Ops[OrigOpNumber].getNode() !=
Op)
2228 assert((OrigOpNumber != Ops.size()) &&
2229 "expected to find TokenFactor Operand");
2231 for (
unsigned i = CurIdx + 1; i < Worklist.
size(); ++i) {
2232 if (Worklist[i].second == OrigOpNumber) {
2233 Worklist[i].second = OpNumber;
2236 OpWorkCount[OpNumber] += OpWorkCount[OrigOpNumber];
2237 OpWorkCount[OrigOpNumber] = 0;
2238 NumLeftToConsider--;
2241 if (SeenChains.
insert(
Op).second) {
2242 OpWorkCount[OpNumber]++;
2247 for (
unsigned i = 0; i < Worklist.
size() && i < 1024; ++i) {
2249 if (NumLeftToConsider <= 1)
2251 auto CurNode = Worklist[i].first;
2252 auto CurOpNumber = Worklist[i].second;
2253 assert((OpWorkCount[CurOpNumber] > 0) &&
2254 "Node should not appear in worklist");
2255 switch (CurNode->getOpcode()) {
2261 NumLeftToConsider++;
2264 for (
const SDValue &
Op : CurNode->op_values())
2265 AddToWorklist(i,
Op.getNode(), CurOpNumber);
2271 AddToWorklist(i, CurNode->getOperand(0).getNode(), CurOpNumber);
2274 if (
auto *MemNode = dyn_cast<MemSDNode>(CurNode))
2275 AddToWorklist(i, MemNode->getChain().getNode(), CurOpNumber);
2278 OpWorkCount[CurOpNumber]--;
2279 if (OpWorkCount[CurOpNumber] == 0)
2280 NumLeftToConsider--;
2294 if (SeenChains.
count(
Op.getNode()) == 0)
2309 WorklistRemover DeadNodes(*
this);
2315 AddUsersToWorklist(
N);
2320 }
while (!
N->use_empty());
2321 deleteAndRecombine(
N);
2329 return Const !=
nullptr && !Const->isOpaque() ? Const :
nullptr;
2339 Op =
N->getOperand(0);
2341 if (
N->getFlags().hasNoUnsignedWrap())
2346 if (
N.getValueType().getScalarType() != MVT::i1 ||
2363 if (LD->isIndexed() || LD->getBasePtr().getNode() !=
N)
2365 VT = LD->getMemoryVT();
2366 AS = LD->getAddressSpace();
2368 if (ST->isIndexed() || ST->getBasePtr().getNode() !=
N)
2370 VT = ST->getMemoryVT();
2371 AS = ST->getAddressSpace();
2373 if (LD->isIndexed() || LD->getBasePtr().getNode() !=
N)
2375 VT = LD->getMemoryVT();
2376 AS = LD->getAddressSpace();
2378 if (ST->isIndexed() || ST->getBasePtr().getNode() !=
N)
2380 VT = ST->getMemoryVT();
2381 AS = ST->getAddressSpace();
2396 }
else if (
N->getOpcode() ==
ISD::SUB) {
2418 bool ShouldCommuteOperands) {
2423 if (ShouldCommuteOperands)
2435 unsigned Opcode =
N->getOpcode();
2436 EVT VT =
N->getValueType(0);
2443 unsigned OpNo = ShouldCommuteOperands ? 0 : 1;
2461 "Unexpected binary operator");
2478 unsigned SelOpNo = 0;
2514 bool CanFoldNonConst =
2520 if (!CanFoldNonConst &&
2528 if (CanFoldNonConst) {
2565 "Expecting add or sub");
2570 bool IsAdd =
N->getOpcode() ==
ISD::ADD;
2571 SDValue C = IsAdd ?
N->getOperand(1) :
N->getOperand(0);
2572 SDValue Z = IsAdd ?
N->getOperand(0) :
N->getOperand(1);
2573 auto *CN = dyn_cast<ConstantSDNode>(
C);
2578 if (Z.getOperand(0).getValueType() != MVT::i1)
2590 EVT VT =
C.getValueType();
2603 if ((!LegalOperations || hasOperation(
ISD::AVGCEILU, VT)) &&
2608 if ((!LegalOperations || hasOperation(
ISD::AVGCEILS, VT)) &&
2621 "Expecting add or sub");
2625 bool IsAdd =
N->getOpcode() ==
ISD::ADD;
2626 SDValue ConstantOp = IsAdd ?
N->getOperand(1) :
N->getOperand(0);
2627 SDValue ShiftOp = IsAdd ?
N->getOperand(0) :
N->getOperand(1);
2649 {ConstantOp, DAG.getConstant(1, DL, VT)})) {
2651 Not.getOperand(0), ShAmt);
2693 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
2725 if ((!LegalOperations ||
2728 X.getScalarValueSizeInBits() == 1) {
2744 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
2748 if (!reassociationCanBreakAddressingModePattern(
ISD::ADD,
DL,
N, N0, N1)) {
2836 return (!Max && !
Op) ||
2837 (
Max &&
Op &&
Max->getAPIntValue() == (-
Op->getAPIntValue()));
2878 !
N->getFlags().hasNoSignedWrap()))) {
2899 (CA * CM + CB->getAPIntValue()).getSExtValue())) {
2903 if (
N->getFlags().hasNoUnsignedWrap() &&
2907 if (
N->getFlags().hasNoSignedWrap() &&
2916 DAG.
getConstant(CA * CM + CB->getAPIntValue(),
DL, VT), Flags);
2924 (CA * CM + CB->getAPIntValue()).getSExtValue())) {
2930 if (
N->getFlags().hasNoUnsignedWrap() &&
2935 if (
N->getFlags().hasNoSignedWrap() &&
2946 DAG.
getConstant(CA * CM + CB->getAPIntValue(),
DL, VT), Flags);
2951 if (
SDValue Combined = visitADDLikeCommutative(N0, N1,
N))
2954 if (
SDValue Combined = visitADDLikeCommutative(N1, N0,
N))
2986 if (
SDValue Combined = visitADDLike(
N))
3026 APInt NewStep = C0 + C1;
3036 APInt NewStep = SV0 + SV1;
3045 unsigned Opcode =
N->getOpcode();
3063 return DAG.
getNode(Opcode,
DL, VT, N1, N0);
3067 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
3087 bool ForceCarryReconstruction =
false) {
3093 V = V.getOperand(0);
3098 if (ForceCarryReconstruction)
3102 V = V.getOperand(0);
3106 if (ForceCarryReconstruction && V.getValueType() == MVT::i1)
3113 if (V.getResNo() != 1)
3120 EVT VT = V->getValueType(0);
3228 if (TN->
getVT() == MVT::i1) {
3245 DAG.
getVTList(VT, Carry.getValueType()), N0,
3258 if (!
N->hasAnyUseOfValue(1))
3291 if (Force && isa<ConstantSDNode>(V))
3298 return V.getOperand(0);
3310 EVT CarryVT =
N->getValueType(1);
3314 if (!
N->hasAnyUseOfValue(1))
3321 return DAG.
getNode(
N->getOpcode(),
DL,
N->getVTList(), N1, N0);
3346 if (
SDValue Combined = visitUADDOLike(N0, N1,
N))
3349 if (
SDValue Combined = visitUADDOLike(N1, N0,
N))
3383 SDValue CarryIn =
N->getOperand(2);
3402 SDValue CarryIn =
N->getOperand(2);
3413 if (!LegalOperations ||
3423 AddToWorklist(CarryExt.
getNode());
3429 if (
SDValue Combined = visitUADDO_CARRYLike(N0, N1, CarryIn,
N))
3432 if (
SDValue Combined = visitUADDO_CARRYLike(N1, N0, CarryIn,
N))
3440 SDValue Ops[] = {N1, N0, CarryIn};
3579 EVT CarryOutType =
N->getValueType(0);
3595 unsigned CarryInOperandNum =
3597 if (Opcode ==
ISD::USUBO && CarryInOperandNum != 1)
3691 SDValue CarryIn =
N->getOperand(2);
3702 if (!LegalOperations ||
3707 if (
SDValue Combined = visitSADDO_CARRYLike(N0, N1, CarryIn,
N))
3710 if (
SDValue Combined = visitSADDO_CARRYLike(N1, N0, CarryIn,
N))
3722 "Illegal truncation");
3748 !(!LegalOperations || hasOperation(
ISD::USUBSAT, DstVT)))
3751 EVT SubVT =
N->getValueType(0);
3819template <
class MatchContextClass>
3842 if ((
BitWidth - Src.getValueType().getScalarSizeInBits()) != BitWidthDiff)
3852 if (!(AndMask.
isMask(AndMaskWidth) && XorMask.
countr_one() >= AndMaskWidth))
3883 auto PeekThroughFreeze = [](
SDValue N) {
3885 return N->getOperand(0);
3889 if (
SDValue V = foldSubCtlzNot<EmptyMatchContext>(
N, DAG))
3894 if (PeekThroughFreeze(N0) == PeekThroughFreeze(N1))
3903 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
3911 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
3934 if (
N->getFlags().hasNoUnsignedWrap())
3940 if (
N->getFlags().hasNoSignedWrap())
3966 if (hasOperation(NewOpc, VT))
4093 if (!reassociationCanBreakAddressingModePattern(
ISD::SUB,
DL,
N, N0, N1) &&
4131 if ((!LegalOperations || hasOperation(
ISD::ABS, VT)) &&
4141 if (GA->getGlobal() == GB->getGlobal())
4149 if (TN->
getVT() == MVT::i1) {
4202 DAG.
getVTList(VT, Carry.getValueType()), NegX, Zero,
4210 if (!C0->isOpaque()) {
4211 const APInt &C0Val = C0->getAPIntValue();
4212 const APInt &MaybeOnes = ~DAG.computeKnownBits(N1).Zero;
4213 if ((C0Val - MaybeOnes) == (C0Val ^ MaybeOnes))
4219 if ((!LegalOperations || hasOperation(
ISD::ABDS, VT)) &&
4231 if ((!LegalOperations || hasOperation(
ISD::ABDU, VT)) &&
4246 unsigned Opcode =
N->getOpcode();
4267 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4293 if (!
N->hasAnyUseOfValue(1))
4320 EVT CarryVT =
N->getValueType(1);
4324 if (!
N->hasAnyUseOfValue(1))
4359 SDValue CarryIn =
N->getOperand(2);
4371 SDValue CarryIn =
N->getOperand(2);
4375 if (!LegalOperations ||
4386 SDValue CarryIn =
N->getOperand(2);
4390 if (!LegalOperations ||
4422template <
class MatchContextClass>
SDValue DAGCombiner::visitMUL(
SDNode *
N) {
4428 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
4429 MatchContextClass Matcher(DAG, TLI,
N);
4442 return Matcher.getNode(
ISD::MUL,
DL, VT, N1, N0);
4444 bool N1IsConst =
false;
4445 bool N1IsOpaqueConst =
false;
4452 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4457 "Splat APInt should be element width");
4459 N1IsConst = isa<ConstantSDNode>(N1);
4462 N1IsOpaqueConst = cast<ConstantSDNode>(N1)->isOpaque();
4467 if (N1IsConst && ConstValue1.
isZero())
4471 if (N1IsConst && ConstValue1.
isOne())
4475 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4479 if (N1IsConst && ConstValue1.
isAllOnes())
4485 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
4494 unsigned Log2Val = (-ConstValue1).logBase2();
4498 return Matcher.getNode(
4512 if (LoHi->hasAnyUseOfValue(1))
4515 if (LoHi->hasAnyUseOfValue(1))
4536 if (!UseVP && N1IsConst &&
4544 unsigned TZeros = MulC == 2 ? 0 : MulC.
countr_zero();
4546 if ((MulC - 1).isPowerOf2())
4548 else if ((MulC + 1).isPowerOf2())
4553 MathOp ==
ISD::ADD ? (MulC - 1).logBase2() : (MulC + 1).logBase2();
4556 "multiply-by-constant generated out of bounds shift");
4560 TZeros ? DAG.
getNode(MathOp,
DL, VT, Shl,
4602 return Matcher.getNode(
4620 APInt NewStep = C0 * MulVal;
4626 if (!UseVP && (!LegalOperations || hasOperation(
ISD::ABS, VT)) &&
4643 if (!V ||
V->isZero()) {
4657 for (
unsigned I = 0;
I != NumElts; ++
I)
4688 EVT NodeType =
Node->getValueType(0);
4689 if (!NodeType.isSimple())
4691 switch (NodeType.getSimpleVT().SimpleTy) {
4692 default:
return false;
4693 case MVT::i8: LC=
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
4694 case MVT::i16: LC=
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
4695 case MVT::i32: LC=
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
4696 case MVT::i64: LC=
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
4697 case MVT::i128: LC=
isSigned ? RTLIB::SDIVREM_I128:RTLIB::UDIVREM_I128;
break;
4705 if (
Node->use_empty())
4708 unsigned Opcode =
Node->getOpcode();
4713 EVT VT =
Node->getValueType(0);
4727 unsigned OtherOpcode = 0;
4748 unsigned UserOpc =
User->getOpcode();
4749 if ((UserOpc == Opcode || UserOpc == OtherOpcode || UserOpc == DivRemOpc) &&
4753 if (UserOpc == OtherOpcode) {
4756 }
else if (UserOpc == DivRemOpc) {
4759 assert(UserOpc == Opcode);
4764 CombineTo(
User, combined);
4775 EVT VT =
N->getValueType(0);
4778 unsigned Opc =
N->getOpcode();
4787 if (DAG.
isUndef(Opc, {N0, N1}))
4798 if (N0C && N0C->
isZero())
4821 EVT VT =
N->getValueType(0);
4831 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4848 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4856 if (
SDValue V = visitSDIVLike(N0, N1,
N)) {
4863 AddToWorklist(
Mul.getNode());
4865 CombineTo(RemNode, Sub);
4885 if (
C->isZero() ||
C->isOpaque())
4887 if (
C->getAPIntValue().isPowerOf2())
4889 if (
C->getAPIntValue().isNegatedPowerOf2())
4899 EVT VT =
N->getValueType(0);
4924 AddToWorklist(Sign.
getNode());
4930 AddToWorklist(
Add.getNode());
4941 Sra = DAG.
getSelect(
DL, VT, IsOneOrAllOnes, N0, Sra);
4969 EVT VT =
N->getValueType(0);
4979 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4993 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4996 if (
SDValue V = visitUDIVLike(N0, N1,
N)) {
5003 AddToWorklist(
Mul.getNode());
5005 CombineTo(RemNode, Sub);
5029 EVT VT =
N->getValueType(0);
5033 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
5034 AddToWorklist(LogBase2.getNode());
5038 AddToWorklist(Trunc.
getNode());
5047 if (
SDValue LogBase2 = BuildLogBase2(N10,
DL)) {
5048 AddToWorklist(LogBase2.getNode());
5052 AddToWorklist(Trunc.
getNode());
5054 AddToWorklist(
Add.getNode());
5082 unsigned Opcode =
N->getOpcode();
5085 EVT VT =
N->getValueType(0);
5107 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
5120 AddToWorklist(
Add.getNode());
5131 AddToWorklist(
Add.getNode());
5148 if (
SDValue OptimizedRem = buildOptimizedSREM(N0, N1,
N))
5149 return OptimizedRem;
5153 isSigned ? visitSDIVLike(N0, N1,
N) : visitUDIVLike(N0, N1,
N);
5159 CombineTo(DivNode, OptimizedDiv);
5162 AddToWorklist(OptimizedDiv.
getNode());
5163 AddToWorklist(
Mul.getNode());
5170 return DivRem.getValue(1);
5178 EVT VT =
N->getValueType(0);
5191 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5219 unsigned SimpleSize =
Simple.getSizeInBits();
5237 EVT VT =
N->getValueType(0);
5250 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5274 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
5289 unsigned SimpleSize =
Simple.getSizeInBits();
5311 unsigned Opcode =
N->getOpcode();
5314 EVT VT =
N->getValueType(0);
5325 return DAG.
getNode(Opcode,
DL,
N->getVTList(), N1, N0);
5328 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5354 X.getValueType() ==
Y.getValueType() &&
5355 hasOperation(Opcode,
X.getValueType())) {
5361 X.getValueType() ==
Y.getValueType() &&
5362 hasOperation(Opcode,
X.getValueType())) {
5395 if (IsSigned &&
Add->getFlags().hasNoSignedWrap())
5398 if (!IsSigned &&
Add->getFlags().hasNoUnsignedWrap())
5407 unsigned Opcode =
N->getOpcode();
5410 EVT VT =
N->getValueType(0);
5420 return DAG.
getNode(Opcode,
DL,
N->getVTList(), N1, N0);
5423 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5438 (!LegalOperations || hasOperation(
ISD::ABS, VT)))
5456SDValue DAGCombiner::SimplifyNodeWithTwoResults(
SDNode *
N,
unsigned LoOp,
5459 bool HiExists =
N->hasAnyUseOfValue(1);
5460 if (!HiExists && (!LegalOperations ||
5463 return CombineTo(
N, Res, Res);
5467 bool LoExists =
N->hasAnyUseOfValue(0);
5468 if (!LoExists && (!LegalOperations ||
5471 return CombineTo(
N, Res, Res);
5475 if (LoExists && HiExists)
5481 AddToWorklist(
Lo.getNode());
5484 (!LegalOperations ||
5486 return CombineTo(
N, LoOpt, LoOpt);
5491 AddToWorklist(
Hi.getNode());
5494 (!LegalOperations ||
5496 return CombineTo(
N, HiOpt, HiOpt);
5508 EVT VT =
N->getValueType(0);
5512 if (isa<ConstantSDNode>(N0) && isa<ConstantSDNode>(N1))
5524 unsigned SimpleSize =
Simple.getSizeInBits();
5536 return CombineTo(
N,
Lo,
Hi);
5549 EVT VT =
N->getValueType(0);
5553 if (isa<ConstantSDNode>(N0) && isa<ConstantSDNode>(N1))
5564 return CombineTo(
N, Zero, Zero);
5570 return CombineTo(
N, N0, Zero);
5577 unsigned SimpleSize =
Simple.getSizeInBits();
5589 return CombineTo(
N,
Lo,
Hi);
5602 EVT CarryVT =
N->getValueType(1);
5623 return DAG.
getNode(
N->getOpcode(),
DL,
N->getVTList(), N1, N0);
5635 N->getVTList(), N0, N0);
5642 return CombineTo(
N,
And, Cmp);
5680 unsigned Opcode0 = isSignedMinMax(N0, N1, N2, N3,
CC);
5718 N0CC = cast<CondCodeSDNode>(N0.
getOperand(4))->get();
5734 unsigned Opcode1 = isSignedMinMax(N00, N01, N02, N03, N0CC);
5735 if (!Opcode1 || Opcode0 == Opcode1)
5745 APInt MinCPlus1 = MinC + 1;
5746 if (-MaxC == MinCPlus1 && MinCPlus1.
isPowerOf2()) {
5803 unsigned BW = (C1 + 1).exactLogBase2();
5823 unsigned Opcode =
N->getOpcode();
5837 return DAG.
getNode(Opcode,
DL, VT, N1, N0);
5841 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5845 if (
SDValue RMINMAX = reassociateOps(Opcode,
DL, N0, N1,
N->getFlags()))
5865 return DAG.
getNode(AltOpcode,
DL, VT, N0, N1);
5877 auto ReductionOpcode = [](
unsigned Opcode) {
5891 if (
SDValue SD = reassociateReduction(ReductionOpcode(Opcode), Opcode,
5905 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
5907 unsigned LogicOpcode =
N->getOpcode();
5922 EVT XVT =
X.getValueType();
5932 if (XVT !=
Y.getValueType())
5936 if ((VT.
isVector() || LegalOperations) &&
5949 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
5959 if (XVT !=
Y.getValueType())
5971 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
5992 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6007 return DAG.
getNode(HandOpcode,
DL, VT, Logic0, Logic1, S);
6020 if (XVT.
isInteger() && XVT ==
Y.getValueType() &&
6024 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6041 auto *SVN0 = cast<ShuffleVectorSDNode>(N0);
6042 auto *SVN1 = cast<ShuffleVectorSDNode>(N1);
6043 assert(
X.getValueType() ==
Y.getValueType() &&
6044 "Inputs to shuffles are not the same type");
6050 if (!SVN0->hasOneUse() || !SVN1->hasOneUse() ||
6051 !SVN0->getMask().equals(SVN1->getMask()))
6087 SDValue LL, LR, RL, RR, N0CC, N1CC;
6088 if (!isSetCCEquivalent(N0, LL, LR, N0CC) ||
6089 !isSetCCEquivalent(N1, RL, RR, N1CC))
6093 "Unexpected operand types for bitwise logic op");
6096 "Unexpected operand types for setcc");
6112 if (LR == RR && CC0 == CC1 && IsInteger) {
6117 bool AndEqZero = IsAnd && CC1 ==
ISD::SETEQ && IsZero;
6119 bool AndGtNeg1 = IsAnd && CC1 ==
ISD::SETGT && IsNeg1;
6121 bool OrNeZero = !IsAnd && CC1 ==
ISD::SETNE && IsZero;
6123 bool OrLtZero = !IsAnd && CC1 ==
ISD::SETLT && IsZero;
6129 if (AndEqZero || AndGtNeg1 || OrNeZero || OrLtZero) {
6131 AddToWorklist(
Or.getNode());
6136 bool AndEqNeg1 = IsAnd && CC1 ==
ISD::SETEQ && IsNeg1;
6138 bool AndLtZero = IsAnd && CC1 ==
ISD::SETLT && IsZero;
6140 bool OrNeNeg1 = !IsAnd && CC1 ==
ISD::SETNE && IsNeg1;
6142 bool OrGtNeg1 = !IsAnd && CC1 ==
ISD::SETGT && IsNeg1;
6148 if (AndEqNeg1 || AndLtZero || OrNeNeg1 || OrGtNeg1) {
6150 AddToWorklist(
And.getNode());
6164 AddToWorklist(
Add.getNode());
6191 return !C0->
isOpaque() && !C1->isOpaque() && (CMax - CMin).isPowerOf2();
6209 if (LL == RR && LR == RL) {
6216 if (LL == RL && LR == RR) {
6220 (!LegalOperations ||
6243 bool isFMAXNUMFMINNUM_IEEE,
6244 bool isFMAXNUMFMINNUM) {
6255 isFMAXNUMFMINNUM_IEEE
6263 isFMAXNUMFMINNUM_IEEE
6281 isFMAXNUMFMINNUM_IEEE
6290 isFMAXNUMFMINNUM_IEEE
6300 "Invalid Op to combine SETCC with");
6311 LogicOp,
LHS.getNode(),
RHS.getNode());
6346 (isFMAXNUMFMINNUM_IEEE || isFMAXNUMFMINNUM))) &&
6352 SDValue CommonValue, Operand1, Operand2;
6360 }
else if (LHS1 == RHS1) {
6373 }
else if (RHS0 == LHS1) {
6390 bool IsSigned = isSignedIntSetCC(
CC);
6402 DAG, isFMAXNUMFMINNUM_IEEE, isFMAXNUMFMINNUM);
6406 DAG.
getNode(NewOpcode,
DL, OpVT, Operand1, Operand2);
6407 return DAG.
getSetCC(
DL, VT, MinMaxValue, CommonValue,
CC);
6417 LHS0 == RHS0 && LHS1C && RHS1C && OpVT.
isInteger()) {
6418 const APInt &APLhs = LHS1C->getAPIntValue();
6419 const APInt &APRhs = RHS1C->getAPIntValue();
6423 if (APLhs == (-APRhs) &&
6434 }
else if (TargetPreference &
6455 APInt Dif = MaxC - MinC;
6489 EVT CondVT =
Cond.getValueType();
6500 EVT OpVT =
T.getValueType();
6519 if (
SDValue V = foldLogicOfSetCCs(
true, N0, N1,
DL))
6537 APInt SRLC = SRLI->getAPIntValue();
6549 CombineTo(N0.
getNode(), NewAdd);
6563 EVT LoadResultTy,
EVT &ExtVT) {
6572 if (ExtVT == LoadedVT &&
6573 (!LegalOperations ||
6589 if (LegalOperations &&
6625 if (LdStMemVT.
bitsLT(MemVT))
6630 assert(ShAmt % 8 == 0 &&
"ShAmt is byte offset");
6631 const unsigned ByteShAmt = ShAmt / 8;
6642 if (PtrType == MVT::Untyped || PtrType.
isExtended())
6645 if (isa<LoadSDNode>(LDST)) {
6649 if (!
SDValue(Load, 0).hasOneUse())
6652 if (LegalOperations &&
6661 if (
Load->getNumValues() > 2)
6674 assert(isa<StoreSDNode>(LDST) &&
"It is not a Load nor a Store SDNode");
6680 if (LegalOperations &&
6687bool DAGCombiner::SearchForAndLoads(
SDNode *
N,
6695 if (
Op.getValueType().isVector())
6699 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
6701 (
Mask->getAPIntValue() &
C->getAPIntValue()) !=
C->getAPIntValue())
6706 if (!
Op.hasOneUse())
6709 switch(
Op.getOpcode()) {
6711 auto *
Load = cast<LoadSDNode>(
Op);
6713 if (isAndLoadExtLoad(Mask, Load,
Load->getValueType(0), ExtVT) &&
6731 unsigned ActiveBits =
Mask->getAPIntValue().countr_one();
6734 cast<VTSDNode>(
Op.getOperand(1))->getVT() :
6735 Op.getOperand(0).getValueType();
6746 if (!SearchForAndLoads(
Op.getNode(), Loads, NodesWithConsts, Mask,
6757 NodeToMask =
Op.getNode();
6760 for (
unsigned i = 0, e = NodeToMask->
getNumValues(); i < e; ++i) {
6762 if (VT != MVT::Glue && VT != MVT::Other) {
6764 NodeToMask =
nullptr;
6776bool DAGCombiner::BackwardsPropagateMask(
SDNode *
N) {
6777 auto *
Mask = dyn_cast<ConstantSDNode>(
N->getOperand(1));
6781 if (!
Mask->getAPIntValue().isMask())
6785 if (isa<LoadSDNode>(
N->getOperand(0)))
6790 SDNode *FixupNode =
nullptr;
6791 if (SearchForAndLoads(
N, Loads, NodesWithConsts, Mask, FixupNode)) {
6804 SDValue(FixupNode, 0), MaskOp);
6806 if (
And.getOpcode() == ISD ::AND)
6811 for (
auto *LogicN : NodesWithConsts) {
6815 if (isa<ConstantSDNode>(Op0))
6819 if (isa<ConstantSDNode>(Op1))
6823 if (isa<ConstantSDNode>(Op0) && !isa<ConstantSDNode>(Op1))
6830 for (
auto *Load : Loads) {
6835 if (
And.getOpcode() == ISD ::AND)
6838 SDValue NewLoad = reduceLoadWidth(
And.getNode());
6840 "Shouldn't be masking the load if it can't be narrowed");
6841 CombineTo(Load, NewLoad, NewLoad.
getValue(1));
6854SDValue DAGCombiner::unfoldExtremeBitClearingToShifts(
SDNode *
N) {
6865 unsigned OuterShift;
6866 unsigned InnerShift;
6868 auto matchMask = [&OuterShift, &InnerShift, &
Y](
SDValue M) ->
bool {
6871 OuterShift =
M->getOpcode();
6880 Y =
M->getOperand(1);
6887 else if (matchMask(N0))
6893 EVT VT =
N->getValueType(0);
6910 SDValue And0 =
And->getOperand(0), And1 =
And->getOperand(1);
6920 bool FoundNot =
false;
6923 Src = Src.getOperand(0);
6929 Src = Src.getOperand(0);
6933 if (Src.getOpcode() !=
ISD::SRL || !Src.hasOneUse())
6937 EVT SrcVT = Src.getValueType();
6944 SDValue ShiftAmt = Src.getOperand(1);
6945 auto *ShiftAmtC = dyn_cast<ConstantSDNode>(ShiftAmt);
6946 if (!ShiftAmtC || !ShiftAmtC->getAPIntValue().ult(
BitWidth))
6950 Src = Src.getOperand(0);
6957 Src = Src.getOperand(0);
6981 EVT VT =
N->getValueType(0);
7007 unsigned LogicOpcode =
N->getOpcode();
7009 "Expected bitwise logic operation");
7015 unsigned ShiftOpcode = ShiftOp.
getOpcode();
7016 if (LogicOp.
getOpcode() != LogicOpcode ||
7040 EVT VT =
N->getValueType(0);
7044 return DAG.
getNode(LogicOpcode,
DL, VT, NewShift, Z);
7055 unsigned LogicOpcode =
N->getOpcode();
7057 "Expected bitwise logic operation");
7058 if (LeftHand.
getOpcode() != LogicOpcode ||
7079 EVT VT =
N->getValueType(0);
7081 return DAG.
getNode(LogicOpcode,
DL, VT, CombinedShifts, W);
7108 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
7122 auto *MLoad = dyn_cast<MaskedLoadSDNode>(N0);
7125 EVT LoadVT = MLoad->getMemoryVT();
7133 if (
Splat->getAPIntValue().isMask(ElementSize)) {
7135 ExtVT,
DL, MLoad->getChain(), MLoad->getBasePtr(),
7136 MLoad->getOffset(), MLoad->getMask(), MLoad->getPassThru(),
7137 LoadVT, MLoad->getMemOperand(), MLoad->getAddressingMode(),
7139 bool LoadHasOtherUsers = !N0.
hasOneUse();
7140 CombineTo(
N, NewLoad);
7141 if (LoadHasOtherUsers)
7162 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
7176 return RHS->getAPIntValue().isSubsetOf(
LHS->getAPIntValue());
7244 unsigned EltBitWidth =
Vector->getValueType(0).getScalarSizeInBits();
7245 APInt SplatValue, SplatUndef;
7246 unsigned SplatBitSize;
7253 const bool IsBigEndian =
false;
7255 Vector->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
7256 HasAnyUndefs, EltBitWidth, IsBigEndian);
7260 if (IsSplat && (SplatBitSize % EltBitWidth) == 0) {
7263 SplatValue |= SplatUndef;
7270 for (
unsigned i = 0, n = (SplatBitSize / EltBitWidth); i < n; ++i)
7279 Load->getValueType(0),
7280 Load->getMemoryVT());
7288 switch (
Load->getExtensionType()) {
7289 default:
B =
false;
break;
7301 CombineTo(
N, (N0.
getNode() == Load) ? NewLoad : N0);
7306 Load->getChain(),
Load->getBasePtr(),
7307 Load->getOffset(),
Load->getMemoryVT(),
7308 Load->getMemOperand());
7310 if (
Load->getNumValues() == 3) {
7314 CombineTo(Load, To, 3,
true);
7316 CombineTo(Load, NewLoad.getValue(0), NewLoad.getValue(1));
7326 if (
SDValue Shuffle = XformToShuffleWithZero(
N))
7335 EVT ExtVT =
Ext->getValueType(0);
7352 if (
auto *GN0 = dyn_cast<MaskedGatherSDNode>(N0)) {
7353 EVT MemVT = GN0->getMemoryVT();
7356 if (
SDValue(GN0, 0).hasOneUse() &&
7359 SDValue Ops[] = {GN0->getChain(), GN0->getPassThru(), GN0->getMask(),
7360 GN0->getBasePtr(), GN0->getIndex(), GN0->getScale()};
7363 DAG.
getVTList(VT, MVT::Other), MemVT,
DL, Ops, GN0->getMemOperand(),
7366 CombineTo(
N, ZExtLoad);
7367 AddToWorklist(ZExtLoad.
getNode());
7376 if (
SDValue Res = reduceLoadWidth(
N))
7384 if (BackwardsPropagateMask(
N))
7388 if (
SDValue Combined = visitANDLike(N0, N1,
N))
7393 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
7440 X.getOperand(0).getScalarValueSizeInBits() == 1)
7443 X.getOperand(0).getScalarValueSizeInBits() == 1)
7457 auto *LN0 = cast<LoadSDNode>(N0);
7458 EVT MemVT = LN0->getMemoryVT();
7465 ((!LegalOperations && LN0->isSimple()) ||
7469 LN0->getBasePtr(), MemVT, LN0->getMemOperand());
7483 if (
SDValue Shifts = unfoldExtremeBitClearingToShifts(
N))
7499 auto *
C = dyn_cast<ConstantSDNode>(RHS);
7503 if (!
C->getAPIntValue().isMask(
7504 LHS.getOperand(0).getValueType().getFixedSizeInBits()))
7511 if (IsAndZeroExtMask(N0, N1))
7520 if (LegalOperations || VT.
isVector())
7529 bool DemandHighBits) {
7530 if (!LegalOperations)
7533 EVT VT =
N->getValueType(0);
7534 if (VT != MVT::i64 && VT != MVT::i32 && VT != MVT::i16)
7540 bool LookPassAnd0 =
false;
7541 bool LookPassAnd1 =
false;
7556 LookPassAnd0 =
true;
7566 LookPassAnd1 =
true;
7592 LookPassAnd0 =
true;
7606 LookPassAnd1 =
true;
7615 if (OpSizeInBits > 16) {
7619 if (DemandHighBits && !LookPassAnd0)
7626 if (!LookPassAnd1) {
7627 unsigned HighBit = DemandHighBits ? OpSizeInBits : 24;
7635 if (OpSizeInBits > 16) {
7650 if (!
N->hasOneUse())
7653 unsigned Opc =
N.getOpcode();
7665 N1C = dyn_cast<ConstantSDNode>(
N.getOperand(1));
7667 N1C = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
7671 unsigned MaskByteOffset;
7675 case 0xFF: MaskByteOffset = 0;
break;
7676 case 0xFF00: MaskByteOffset = 1;
break;
7685 case 0xFF0000: MaskByteOffset = 2;
break;
7686 case 0xFF000000: MaskByteOffset = 3;
break;
7691 if (MaskByteOffset == 0 || MaskByteOffset == 2) {
7697 if (!
C ||
C->getZExtValue() != 8)
7705 if (!
C ||
C->getZExtValue() != 8)
7711 if (MaskByteOffset != 0 && MaskByteOffset != 2)
7714 if (!
C ||
C->getZExtValue() != 8)
7719 if (MaskByteOffset != 1 && MaskByteOffset != 3)
7722 if (!
C ||
C->getZExtValue() != 8)
7726 if (Parts[MaskByteOffset])
7741 if (!
C ||
C->getAPIntValue() != 16)
7743 Parts[0] = Parts[1] =
N.getOperand(0).getOperand(0).getNode();
7758 "MatchBSwapHWordOrAndAnd: expecting i32");
7768 if (!Mask0 || !Mask1)
7779 if (!ShiftAmt0 || !ShiftAmt1)
7799 if (!LegalOperations)
7802 EVT VT =
N->getValueType(0);
7840 if (Parts[0] != Parts[1] || Parts[0] != Parts[2] || Parts[0] != Parts[3])
7868 if (
SDValue V = foldLogicOfSetCCs(
false, N0, N1,
DL))
7883 const APInt &LHSMask = N0O1C->getAPIntValue();
7884 const APInt &RHSMask = N1O1C->getAPIntValue();
7918 auto peekThroughResize = [](
SDValue V) {
7920 return V->getOperand(0);
7924 SDValue N0Resized = peekThroughResize(N0);
7926 SDValue N1Resized = peekThroughResize(N1);
7931 if (N00 == N1Resized || N01 == N1Resized)
7938 if (peekThroughResize(NotOperand) == N1Resized)
7946 if (peekThroughResize(NotOperand) == N1Resized)
7967 auto peekThroughZext = [](
SDValue V) {
7969 return V->getOperand(0);
7991 Lo.getScalarValueSizeInBits() == (BW / 2) &&
7992 Lo.getValueType() ==
Hi.getValueType()) {
8029 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
8043 auto *SV0 = dyn_cast<ShuffleVectorSDNode>(N0);
8044 auto *SV1 = dyn_cast<ShuffleVectorSDNode>(N1);
8051 if ((ZeroN00 != ZeroN01) && (ZeroN10 != ZeroN11)) {
8052 assert((!ZeroN00 || !ZeroN01) &&
"Both inputs zero!");
8053 assert((!ZeroN10 || !ZeroN11) &&
"Both inputs zero!");
8054 bool CanFold =
true;
8058 for (
int i = 0; i != NumElts; ++i) {
8059 int M0 = SV0->getMaskElt(i);
8060 int M1 = SV1->getMaskElt(i);
8063 bool M0Zero =
M0 < 0 || (ZeroN00 == (
M0 < NumElts));
8064 bool M1Zero =
M1 < 0 || (ZeroN10 == (
M1 < NumElts));
8068 if ((M0Zero &&
M1 < 0) || (M1Zero &&
M0 < 0))
8072 if (M0Zero == M1Zero) {
8077 assert((
M0 >= 0 ||
M1 >= 0) &&
"Undef index!");
8083 Mask[i] = M1Zero ?
M0 % NumElts : (
M1 % NumElts) + NumElts;
8092 return LegalShuffle;
8106 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
8117 if (
SDValue Combined = visitORLike(N0, N1,
DL))
8124 if (
SDValue BSwap = MatchBSwapHWord(
N, N0, N1))
8126 if (
SDValue BSwap = MatchBSwapHWordLow(
N, N0, N1))
8160 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
8164 if (
SDValue Rot = MatchRotate(N0, N1,
DL))
8167 if (
SDValue Load = MatchLoadCombine(
N))
8177 if (
SDValue Combined = visitADDLike(
N))
8182 if (LegalOperations || VT.
isVector())
8193 Mask =
Op.getOperand(1);
8194 return Op.getOperand(0);
8237 assert(OppShift && ExtractFrom &&
"Empty SDValue");
8265 bool IsMulOrDiv =
false;
8268 auto SelectOpcode = [&](
unsigned NeededShift,
unsigned MulOrDivVariant) {
8269 IsMulOrDiv = ExtractFrom.
getOpcode() == MulOrDivVariant;
8270 if (!IsMulOrDiv && ExtractFrom.
getOpcode() != NeededShift)
8272 Opcode = NeededShift;
8322 if (Rem != 0 || ResultAmt != OppLHSAmt)
8328 if (OppLHSAmt != ExtractFromAmt - NeededShiftAmt.
zextOrTrunc(
8337 return DAG.
getNode(Opcode,
DL, ResVT, OppShiftLHS, NewShiftNode);
8391 unsigned MaskLoBits = 0;
8393 unsigned Bits =
Log2_64(EltSize);
8395 if (NegBits >= Bits) {
8418 if (PosBits >= MaskLoBits) {
8440 if ((Pos == NegOp1) ||
8464 return Width.
getLoBits(MaskLoBits) == 0;
8465 return Width == EltSize;
8475 SDValue InnerNeg,
bool HasPos,
8476 unsigned PosOpcode,
unsigned NegOpcode,
8488 return DAG.
getNode(HasPos ? PosOpcode : NegOpcode,
DL, VT, Shifted,
8489 HasPos ? Pos : Neg);
8503 SDValue InnerNeg,
bool HasPos,
8504 unsigned PosOpcode,
unsigned NegOpcode,
8516 if (
matchRotateSub(InnerPos, InnerNeg, EltBits, DAG, N0 == N1)) {
8517 return DAG.
getNode(HasPos ? PosOpcode : NegOpcode,
DL, VT, N0, N1,
8518 HasPos ? Pos : Neg);
8525 auto IsBinOpImm = [](
SDValue Op,
unsigned BinOpc,
unsigned Imm) {
8526 if (
Op.getOpcode() != BinOpc)
8535 IsBinOpImm(InnerNeg,
ISD::XOR, EltBits - 1) &&
8544 IsBinOpImm(InnerPos,
ISD::XOR, EltBits - 1) &&
8554 IsBinOpImm(InnerPos,
ISD::XOR, EltBits - 1) &&
8569 EVT VT =
LHS.getValueType();
8574 bool HasROTL = hasOperation(
ISD::ROTL, VT);
8575 bool HasROTR = hasOperation(
ISD::ROTR, VT);
8576 bool HasFSHL = hasOperation(
ISD::FSHL, VT);
8577 bool HasFSHR = hasOperation(
ISD::FSHR, VT);
8588 if (LegalOperations && !HasROTL && !HasROTR && !HasFSHL && !HasFSHR)
8593 LHS.getOperand(0).getValueType() ==
RHS.getOperand(0).getValueType()) {
8595 if (
SDValue Rot = MatchRotate(
LHS.getOperand(0),
RHS.getOperand(0),
DL)) {
8610 if (!LHSShift && !RHSShift)
8625 RHSShift = NewRHSShift;
8630 LHSShift = NewLHSShift;
8633 if (!RHSShift || !LHSShift)
8660 return (
LHS->getAPIntValue() +
RHS->getAPIntValue()) == EltSizeInBits;
8663 auto ApplyMasks = [&](
SDValue Res) {
8687 bool IsRotate = LHSShiftArg == RHSShiftArg;
8688 if (!IsRotate && !(HasFSHL || HasFSHR)) {
8697 if (CommonOp ==
Or.getOperand(0)) {
8699 Y =
Or.getOperand(1);
8702 if (CommonOp ==
Or.getOperand(1)) {
8704 Y =
Or.getOperand(0);
8711 if (matchOr(LHSShiftArg, RHSShiftArg)) {
8716 }
else if (matchOr(RHSShiftArg, LHSShiftArg)) {
8725 return ApplyMasks(Res);
8738 if (IsRotate && (HasROTL || HasROTR || !(HasFSHL || HasFSHR))) {
8739 bool UseROTL = !LegalOperations || HasROTL;
8741 UseROTL ? LHSShiftAmt : RHSShiftAmt);
8743 bool UseFSHL = !LegalOperations || HasFSHL;
8745 RHSShiftArg, UseFSHL ? LHSShiftAmt : RHSShiftAmt);
8748 return ApplyMasks(Res);
8753 if (!HasROTL && !HasROTR && !HasFSHL && !HasFSHR)
8762 SDValue LExtOp0 = LHSShiftAmt;
8763 SDValue RExtOp0 = RHSShiftAmt;
8776 if (IsRotate && (HasROTL || HasROTR)) {
8778 MatchRotatePosNeg(LHSShiftArg, LHSShiftAmt, RHSShiftAmt, LExtOp0,
8784 MatchRotatePosNeg(RHSShiftArg, RHSShiftAmt, LHSShiftAmt, RExtOp0,
8791 MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, LHSShiftAmt, RHSShiftAmt,
8797 MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, RHSShiftAmt, LHSShiftAmt,
8848static std::optional<SDByteProvider>
8850 std::optional<uint64_t> VectorIndex,
8851 unsigned StartingIndex = 0) {
8855 return std::nullopt;
8859 if (
Depth && !
Op.hasOneUse() &&
8860 (
Op.getOpcode() !=
ISD::LOAD || !
Op.getValueType().isVector()))
8861 return std::nullopt;
8865 if (
Op.getOpcode() !=
ISD::LOAD && VectorIndex.has_value())
8866 return std::nullopt;
8870 return std::nullopt;
8872 assert(Index < ByteWidth &&
"invalid index requested");
8875 switch (
Op.getOpcode()) {
8880 return std::nullopt;
8884 return std::nullopt;
8886 if (
LHS->isConstantZero())
8888 if (
RHS->isConstantZero())
8890 return std::nullopt;
8893 auto ShiftOp = dyn_cast<ConstantSDNode>(
Op->getOperand(1));
8895 return std::nullopt;
8897 uint64_t BitShift = ShiftOp->getZExtValue();
8899 if (BitShift % 8 != 0)
8900 return std::nullopt;
8906 return Index < ByteShift
8909 Depth + 1, VectorIndex, Index);
8916 if (NarrowBitWidth % 8 != 0)
8917 return std::nullopt;
8918 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
8920 if (Index >= NarrowByteWidth)
8922 ? std::optional<SDByteProvider>(
8930 Depth + 1, VectorIndex, StartingIndex);
8932 auto OffsetOp = dyn_cast<ConstantSDNode>(
Op->getOperand(1));
8934 return std::nullopt;
8936 VectorIndex = OffsetOp->getZExtValue();
8940 if (NarrowBitWidth % 8 != 0)
8941 return std::nullopt;
8942 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
8945 if (Index >= NarrowByteWidth)
8946 return std::nullopt;
8954 if (*VectorIndex * NarrowByteWidth > StartingIndex)
8955 return std::nullopt;
8956 if ((*VectorIndex + 1) * NarrowByteWidth <= StartingIndex)
8957 return std::nullopt;
8960 VectorIndex, StartingIndex);
8963 auto L = cast<LoadSDNode>(
Op.getNode());
8964 if (!L->isSimple() || L->isIndexed())
8965 return std::nullopt;
8967 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
8968 if (NarrowBitWidth % 8 != 0)
8969 return std::nullopt;
8970 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
8975 if (Index >= NarrowByteWidth)
8977 ? std::optional<SDByteProvider>(
8981 unsigned BPVectorIndex = VectorIndex.value_or(0U);
8986 return std::nullopt;
9001 int64_t FirstOffset) {
9003 unsigned Width = ByteOffsets.
size();
9005 return std::nullopt;
9007 bool BigEndian =
true, LittleEndian =
true;
9008 for (
unsigned i = 0; i < Width; i++) {
9009 int64_t CurrentByteOffset = ByteOffsets[i] - FirstOffset;
9012 if (!BigEndian && !LittleEndian)
9013 return std::nullopt;
9016 assert((BigEndian != LittleEndian) &&
"It should be either big endian or"
9023 switch (
Value.getOpcode()) {
9028 return Value.getOperand(0);
9066 EVT MemVT =
N->getMemoryVT();
9067 if (!(MemVT == MVT::i8 || MemVT == MVT::i16 || MemVT == MVT::i32) ||
9068 !
N->isSimple() ||
N->isIndexed())
9075 unsigned MaxWideNumBits = 64;
9076 unsigned MaxStores = MaxWideNumBits / NarrowNumBits;
9077 while (
auto *Store = dyn_cast<StoreSDNode>(Chain)) {
9085 if (
Store->getMemoryVT() != MemVT || !
Store->isSimple() ||
9089 Chain =
Store->getChain();
9090 if (MaxStores < Stores.
size())
9094 if (Stores.
size() < 2)
9099 unsigned NumStores = Stores.
size();
9100 unsigned WideNumBits = NumStores * NarrowNumBits;
9102 if (WideVT != MVT::i16 && WideVT != MVT::i32 && WideVT != MVT::i64)
9111 std::optional<BaseIndexOffset>
Base;
9112 for (
auto *Store : Stores) {
9123 isa<ConstantSDNode>(WideVal.
getOperand(1))) {
9131 if (ShiftAmtC % NarrowNumBits != 0)
9138 Offset = ShiftAmtC / NarrowNumBits;
9144 SourceValue = WideVal;
9145 else if (SourceValue != WideVal) {
9153 SourceValue = WideVal;
9162 int64_t ByteOffsetFromBase = 0;
9165 else if (!
Base->equalBaseIndex(
Ptr, DAG, ByteOffsetFromBase))
9169 if (ByteOffsetFromBase < FirstOffset) {
9171 FirstOffset = ByteOffsetFromBase;
9175 if (Offset < 0 || Offset >= NumStores || OffsetMap[
Offset] !=
INT64_MAX)
9177 OffsetMap[
Offset] = ByteOffsetFromBase;
9181 assert(FirstStore &&
"First store must be set");
9188 if (!Allowed || !
Fast)
9193 auto checkOffsets = [&](
bool MatchLittleEndian) {
9194 if (MatchLittleEndian) {
9195 for (
unsigned i = 0; i != NumStores; ++i)
9196 if (OffsetMap[i] != i * (NarrowNumBits / 8) + FirstOffset)
9199 for (
unsigned i = 0, j = NumStores - 1; i != NumStores; ++i, --
j)
9200 if (OffsetMap[j] != i * (NarrowNumBits / 8) + FirstOffset)
9207 bool NeedBswap =
false;
9208 bool NeedRotate =
false;
9211 if (NarrowNumBits == 8 && checkOffsets(Layout.
isBigEndian()))
9213 else if (NumStores == 2 && checkOffsets(Layout.
isBigEndian()))
9222 "Unexpected store value to merge");
9231 }
else if (NeedRotate) {
9232 assert(WideNumBits % 2 == 0 &&
"Unexpected type for rotate");
9278 "Can only match load combining against OR nodes");
9281 EVT VT =
N->getValueType(0);
9282 if (VT != MVT::i16 && VT != MVT::i32 && VT != MVT::i64)
9288 assert(
P.hasSrc() &&
"Must be a memory byte provider");
9289 auto *
Load = cast<LoadSDNode>(
P.Src.value());
9291 unsigned LoadBitWidth =
Load->getMemoryVT().getScalarSizeInBits();
9293 assert(LoadBitWidth % 8 == 0 &&
9294 "can only analyze providers for individual bytes not bit");
9295 unsigned LoadByteWidth = LoadBitWidth / 8;
9300 std::optional<BaseIndexOffset>
Base;
9304 std::optional<SDByteProvider> FirstByteProvider;
9310 unsigned ZeroExtendedBytes = 0;
9311 for (
int i = ByteWidth - 1; i >= 0; --i) {
9318 if (
P->isConstantZero()) {
9321 if (++ZeroExtendedBytes != (ByteWidth -
static_cast<unsigned>(i)))
9325 assert(
P->hasSrc() &&
"provenance should either be memory or zero");
9326 auto *
L = cast<LoadSDNode>(
P->Src.value());
9332 else if (Chain != LChain)
9337 int64_t ByteOffsetFromBase = 0;
9346 if (
L->getMemoryVT().isVector()) {
9347 unsigned LoadWidthInBit =
L->getMemoryVT().getScalarSizeInBits();
9348 if (LoadWidthInBit % 8 != 0)
9350 unsigned ByteOffsetFromVector =
P->SrcOffset * LoadWidthInBit / 8;
9351 Ptr.addToOffset(ByteOffsetFromVector);
9357 else if (!
Base->equalBaseIndex(
Ptr, DAG, ByteOffsetFromBase))
9361 ByteOffsetFromBase += MemoryByteOffset(*
P);
9362 ByteOffsets[i] = ByteOffsetFromBase;
9365 if (ByteOffsetFromBase < FirstOffset) {
9366 FirstByteProvider =
P;
9367 FirstOffset = ByteOffsetFromBase;
9373 assert(!Loads.
empty() &&
"All the bytes of the value must be loaded from "
9374 "memory, so there must be at least one load which produces the value");
9375 assert(
Base &&
"Base address of the accessed memory location must be set");
9378 bool NeedsZext = ZeroExtendedBytes > 0;
9389 if (LegalOperations &&
9397 ArrayRef(ByteOffsets).drop_back(ZeroExtendedBytes), FirstOffset);
9401 assert(FirstByteProvider &&
"must be set");
9405 if (MemoryByteOffset(*FirstByteProvider) != 0)
9407 auto *FirstLoad = cast<LoadSDNode>(FirstByteProvider->Src.value());
9414 bool NeedsBswap = IsBigEndianTarget != *IsBigEndian;
9421 if (NeedsBswap && (LegalOperations || NeedsZext) &&
9427 if (NeedsBswap && NeedsZext && LegalOperations &&
9435 *FirstLoad->getMemOperand(), &
Fast);
9436 if (!Allowed || !
Fast)
9441 Chain, FirstLoad->getBasePtr(),
9442 FirstLoad->getPointerInfo(), MemVT, FirstLoad->getAlign());
9482 EVT VT =
N->getValueType(0);
9504 M =
And.getOperand(XorIdx ? 0 : 1);
9510 if (!matchAndXor(N0, 0, N1) && !matchAndXor(N0, 1, N1) &&
9511 !matchAndXor(N1, 0, N0) && !matchAndXor(N1, 1, N0))
9517 if (isa<ConstantSDNode>(
M.getNode()))
9585 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
9597 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
9618 if (
SDValue Combined = visitADDLike(
N))
9625 isSetCCEquivalent(N0, LHS, RHS,
CC,
true)) {
9627 LHS.getValueType());
9628 if (!LegalOperations ||
9646 CombineTo(
N, SetCC);
9648 recursivelyDeleteUnusedNodes(N0.
getNode());
9664 AddToWorklist(
V.getNode());
9673 if (isOneUseSetCC(N01) || isOneUseSetCC(N00)) {
9678 return DAG.
getNode(NewOpcode,
DL, VT, N00, N01);
9686 if (isa<ConstantSDNode>(N01) || isa<ConstantSDNode>(N00)) {
9691 return DAG.
getNode(NewOpcode,
DL, VT, N00, N01);
9714 AddToWorklist(NotX.
getNode());
9719 if (!LegalOperations || hasOperation(
ISD::ABS, VT)) {
9723 SDValue A0 =
A.getOperand(0), A1 =
A.getOperand(1);
9725 if ((A0 == S && A1 == S0) || (A1 == S && A0 == S0))
9762 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
9773 if (
SDValue MM = unfoldMaskedMerge(
N))
9796 unsigned LogicOpcode = LogicOp.
getOpcode();
9802 unsigned ShiftOpcode = Shift->
getOpcode();
9805 assert(C1Node &&
"Expected a shift with constant operand");
9808 const APInt *&ShiftAmtVal) {
9809 if (V.getOpcode() != ShiftOpcode || !V.hasOneUse())
9817 ShiftOp = V.getOperand(0);
9822 if (ShiftAmtVal->getBitWidth() != C1Val.
getBitWidth())
9827 bool Overflow =
false;
9828 APInt NewShiftAmt = C1Val.
uadd_ov(*ShiftAmtVal, Overflow);
9833 if (NewShiftAmt.
uge(V.getScalarValueSizeInBits()))
9842 if (matchFirstShift(LogicOp.
getOperand(0),
X, C0Val))
9844 else if (matchFirstShift(LogicOp.
getOperand(1),
X, C0Val))
9856 return DAG.
getNode(LogicOpcode,
DL, VT, NewShift1, NewShift2,
9886 switch (
LHS.getOpcode()) {
9906 isa<ConstantSDNode>(BinOpLHSVal.
getOperand(1));
9910 if (!IsShiftByConstant && !IsCopyOrSelect)
9913 if (IsCopyOrSelect &&
N->hasOneUse())
9918 EVT VT =
N->getValueType(0);
9920 N->getOpcode(),
DL, VT, {LHS.getOperand(1), N->getOperand(1)})) {
9923 return DAG.
getNode(
LHS.getOpcode(),
DL, VT, NewShift, NewRHS);
9934 EVT TruncVT =
N->getValueType(0);
9935 if (
N->hasOneUse() &&
N->getOperand(0).hasOneUse() &&
9937 SDValue N01 =
N->getOperand(0).getOperand(1);
9940 SDValue N00 =
N->getOperand(0).getOperand(0);
9943 AddToWorklist(Trunc00.
getNode());
9944 AddToWorklist(Trunc01.
getNode());
9956 EVT VT =
N->getValueType(0);
9971 bool OutOfRange =
false;
9973 OutOfRange |=
C->getAPIntValue().uge(Bitsize);
9981 return DAG.
getNode(
N->getOpcode(), dl, VT, N0, Amt);
9986 if (RotAmtC && RotAmtC->getAPIntValue() == 8 &&
9998 return DAG.
getNode(
N->getOpcode(), dl, VT, N0, NewOp1);
10010 bool SameSide = (
N->getOpcode() == NextOp);
10017 if (Norm1 && Norm2)
10019 CombineOp, dl, ShiftVT, {Norm1, Norm2})) {
10021 {CombinedShift, BitsizeC});
10023 ISD::UREM, dl, ShiftVT, {CombinedShift, BitsizeC});
10025 CombinedShiftNorm);
10049 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10072 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10082 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10093 return (c1 + c2).uge(OpSizeInBits);
10103 return (c1 + c2).ult(OpSizeInBits);
10130 return c2.
uge(OpSizeInBits - InnerBitwidth) &&
10131 (c1 + c2).uge(OpSizeInBits);
10143 return c2.
uge(OpSizeInBits - InnerBitwidth) &&
10144 (c1 + c2).ult(OpSizeInBits);
10168 return c1.
ult(VT.getScalarSizeInBits()) && (c1 == c2);
10176 AddToWorklist(NewSHL.
getNode());
10184 const APInt &LHSC =
LHS->getAPIntValue();
10185 const APInt &RHSC =
RHS->getAPIntValue();
10186 return LHSC.
ult(OpSizeInBits) && RHSC.
ult(OpSizeInBits) &&
10258 AddToWorklist(Shl0.
getNode());
10277 {Add.getOperand(1)})) {
10297 if (
SDValue NewSHL = visitShiftByConstant(
N))
10331 APInt NewStep = C0 << ShlVal;
10346 "SRL or SRA node is required here!");
10355 SDValue ShiftOperand =
N->getOperand(0);
10366 if (!IsSignExt && !IsZeroExt)
10373 auto UserOfLowerBits = [NarrowVTSize](
SDNode *U) {
10378 if (!UShiftAmtSrc) {
10382 return UShiftAmt < NarrowVTSize;
10396 unsigned ActiveBits = IsSignExt
10397 ?
Constant->getAPIntValue().getSignificantBits()
10398 :
Constant->getAPIntValue().getActiveBits();
10399 if (ActiveBits > NarrowVTSize)
10416 "Cannot have a multiply node with two different operand types.");
10427 if (ShiftAmt != NarrowVTSize)
10449 bool IsSigned =
N->getOpcode() ==
ISD::SRA;
10456 unsigned Opcode =
N->getOpcode();
10461 EVT VT =
N->getValueType(0);
10511 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10514 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10530 APInt Sum = c1 + c2;
10531 unsigned ShiftSum =
10542 "Expected matchBinaryPredicate to return one element for "
10546 ShiftValue = ShiftValues[0];
10574 if ((ShiftAmt > 0) &&
10584 N->getValueType(0), Trunc);
10619 DAG.
getConstant(AddC->getAPIntValue().lshr(ShiftAmt).trunc(
10636 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10653 if (LargeShift->getAPIntValue() == TruncBits) {
10674 if (
SDValue NewSRA = visitShiftByConstant(
N))
10683 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
10686 if (
SDValue AVG = foldShiftToAvg(
N))
10709 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10712 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10728 return (c1 + c2).uge(OpSizeInBits);
10738 return (c1 + c2).ult(OpSizeInBits);
10758 if (c1 + OpSizeInBits == InnerShiftSize) {
10759 if (c1 + c2 >= InnerShiftSize)
10769 c1 + c2 < InnerShiftSize) {
10774 OpSizeInBits - c2),
10789 const APInt &LHSC =
LHS->getAPIntValue();
10790 const APInt &RHSC =
RHS->getAPIntValue();
10791 return LHSC.
ult(OpSizeInBits) && RHSC.
ult(OpSizeInBits) &&
10832 AddToWorklist(SmallShift.
getNode());
10860 APInt UnknownBits = ~Known.Zero;
10876 AddToWorklist(
Op.getNode());
10885 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10895 if (
SDValue NewSRL = visitShiftByConstant(
N))
10899 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
10926 if (
N->hasOneUse()) {
10935 AddToWorklist(
User);
10943 if (
SDValue AVG = foldShiftToAvg(
N))
10950 EVT VT =
N->getValueType(0);
10963 return IsFSHL ? N0 : N1;
10965 auto IsUndefOrZero = [](
SDValue V) {
10976 return DAG.
getNode(
N->getOpcode(),
DL, VT, N0, N1,
10982 return IsFSHL ? N0 : N1;
10988 if (IsUndefOrZero(N0))
10992 if (IsUndefOrZero(N1))
11004 auto *
LHS = dyn_cast<LoadSDNode>(N0);
11005 auto *
RHS = dyn_cast<LoadSDNode>(N1);
11006 if (LHS && RHS &&
LHS->isSimple() &&
RHS->isSimple() &&
11007 LHS->getAddressSpace() ==
RHS->getAddressSpace() &&
11017 RHS->getAddressSpace(), NewAlign,
11018 RHS->getMemOperand()->getFlags(), &
Fast) &&
11022 AddToWorklist(NewPtr.
getNode());
11024 VT,
DL,
RHS->getChain(), NewPtr,
11025 RHS->getPointerInfo().getWithOffset(PtrOff), NewAlign,
11026 RHS->getMemOperand()->getFlags(),
RHS->getAAInfo());
11028 WorklistRemover DeadNodes(*
this);
11055 if (N0 == N1 && hasOperation(RotOpc, VT))
11056 return DAG.
getNode(RotOpc,
DL, VT, N0, N2);
11101 EVT SrcVT =
N->getValueType(0);
11104 N =
N->getOperand(0).getNode();
11109 EVT VT =
N->getValueType(0);
11110 SDValue AbsOp1 =
N->getOperand(0);
11138 VT0 = cast<VTSDNode>(Op0.
getOperand(1))->getVT();
11139 VT1 = cast<VTSDNode>(Op1.
getOperand(1))->getVT();
11148 EVT MaxVT = VT0.
bitsGT(VT1) ? VT0 : VT1;
11149 if ((VT0 == MaxVT || Op0->
hasOneUse()) &&
11151 (!LegalTypes || hasOperation(ABDOpcode, MaxVT))) {
11161 if (!LegalOperations || hasOperation(ABDOpcode, VT)) {
11171 EVT VT =
N->getValueType(0);
11206 EVT VT =
N->getValueType(0);
11229 auto *ShAmt = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
11231 if (ShAmt && ShAmt->getAPIntValue().ult(BW) &&
11232 ShAmt->getZExtValue() >= (BW / 2) &&
11233 (ShAmt->getZExtValue() % 16) == 0 && TLI.
isTypeLegal(HalfVT) &&
11235 (!LegalOperations || hasOperation(
ISD::BSWAP, HalfVT))) {
11237 if (
uint64_t NewShAmt = (ShAmt->getZExtValue() - (BW / 2)))
11252 auto *ShAmt = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
11253 if (ShAmt && ShAmt->getAPIntValue().ult(BW) &&
11254 ShAmt->getZExtValue() % 8 == 0) {
11269 EVT VT =
N->getValueType(0);
11297 EVT VT =
N->getValueType(0);
11314 EVT VT =
N->getValueType(0);
11326 EVT VT =
N->getValueType(0);
11343 EVT VT =
N->getValueType(0);
11355 EVT VT =
N->getValueType(0);
11367 const APInt &Amt = AmtC->getAPIntValue();
11368 if (Amt.
ult(NumBits)) {
11402 EVT VT =
LHS.getValueType();
11408 return (Flags.hasNoSignedZeros() ||
Options.NoSignedZerosFPMath) &&
11410 (Flags.hasNoNaNs() ||
11460 const unsigned Opcode =
N->getOpcode();
11466 unsigned FloorISD = 0;
11467 auto VT =
N->getValueType(0);
11468 bool IsUnsigned =
false;
11497 if (IsUnsigned && !
Add->getFlags().hasNoUnsignedWrap())
11500 if (!IsUnsigned && !
Add->getFlags().hasNoSignedWrap())
11503 return DAG.
getNode(FloorISD,
SDLoc(
N),
N->getValueType(0), {A, B});
11510 if ((LHS == True && RHS == False) || (LHS == False && RHS == True))
11516 True, DAG, LegalOperations, ForCodeSize);
11528 if (LHS == NegTrue) {
11532 RHS, DAG, LegalOperations, ForCodeSize);
11535 if (NegRHS == False) {
11537 False,
CC, TLI, DAG);
11557 EVT VT =
N->getValueType(0);
11559 VT !=
Cond.getOperand(0).getValueType())
11606 EVT VT =
N->getValueType(0);
11607 EVT CondVT =
Cond.getValueType();
11613 auto *C1 = dyn_cast<ConstantSDNode>(N1);
11614 auto *C2 = dyn_cast<ConstantSDNode>(N2);
11618 if (CondVT != MVT::i1 || LegalOperations) {
11633 C1->
isZero() && C2->isOne()) {
11648 assert(CondVT == MVT::i1 && !LegalOperations);
11651 if (C1->
isOne() && C2->isZero())
11659 if (C1->
isZero() && C2->isOne()) {
11666 if (C1->
isZero() && C2->isAllOnes()) {
11679 const APInt &C1Val = C1->getAPIntValue();
11680 const APInt &C2Val = C2->getAPIntValue();
11683 if (C1Val - 1 == C2Val) {
11689 if (C1Val + 1 == C2Val) {
11709 if (C2->isAllOnes()) {
11721template <
class MatchContextClass>
11725 N->getOpcode() == ISD::VP_SELECT) &&
11726 "Expected a (v)(vp.)select");
11728 SDValue T =
N->getOperand(1),
F =
N->getOperand(2);
11729 EVT VT =
N->getValueType(0);
11731 MatchContextClass matcher(DAG, TLI,
N);
11767 EVT VT =
N->getValueType(0);
11831 EVT VT =
LHS.getValueType();
11833 if (LegalOperations && !hasOperation(ABDOpc, VT))
11843 return DAG.
getNode(ABDOpc,
DL, VT, LHS, RHS);
11846 hasOperation(ABDOpc, VT))
11855 return DAG.
getNode(ABDOpc,
DL, VT, LHS, RHS);
11858 hasOperation(ABDOpc, VT))
11872 EVT VT =
N->getValueType(0);
11880 if (
SDValue V = foldBoolSelectToLogic<EmptyMatchContext>(
N,
DL, DAG))
11890 if (
SDValue V = foldSelectOfConstants(
N))
11894 if (SimplifySelectOps(
N, N1, N2))
11897 if (VT0 == MVT::i1) {
11906 bool normalizeToSequence =
11915 if (normalizeToSequence || !InnerSelect.
use_empty())
11917 InnerSelect, N2, Flags);
11920 recursivelyDeleteUnusedNodes(InnerSelect.
getNode());
11927 Cond1, N1, N2, Flags);
11928 if (normalizeToSequence || !InnerSelect.
use_empty())
11930 InnerSelect, Flags);
11933 recursivelyDeleteUnusedNodes(InnerSelect.
getNode());
11943 if (!normalizeToSequence) {
11949 if (
SDValue Combined = visitANDLike(N0, N1_0,
N)) {
11962 if (!normalizeToSequence) {
11968 if (
SDValue Combined = visitORLike(N0, N2_0,
DL))
12004 combineMinNumMaxNum(
DL, VT, Cond0, Cond1, N1, N2,
CC))
12015 auto *
C = dyn_cast<ConstantSDNode>(N2.
getOperand(1));
12016 auto *NotC = dyn_cast<ConstantSDNode>(Cond1);
12017 if (
C && NotC &&
C->getAPIntValue() == ~NotC->getAPIntValue()) {
12037 (!LegalOperations &&
12048 if (
SDValue ABD = foldSelectToABD(Cond0, Cond1, N1, N2,
CC,
DL))
12051 if (
SDValue NewSel = SimplifySelect(
DL, N0, N1, N2))
12056 if (
SDValue BinOp = foldSelectOfBinops(
N))
12072 EVT VT =
N->getValueType(0);
12080 if (
LHS->getNumOperands() != 2 ||
RHS->getNumOperands() != 2)
12089 for (
int i = 0; i < NumElems / 2; ++i) {
12090 if (
Cond->getOperand(i)->isUndef())
12093 if (BottomHalf ==
nullptr)
12094 BottomHalf = cast<ConstantSDNode>(
Cond.getOperand(i));
12095 else if (
Cond->getOperand(i).getNode() != BottomHalf)
12101 for (
int i = NumElems / 2; i < NumElems; ++i) {
12102 if (
Cond->getOperand(i)->isUndef())
12105 if (TopHalf ==
nullptr)
12106 TopHalf = cast<ConstantSDNode>(
Cond.getOperand(i));
12107 else if (
Cond->getOperand(i).getNode() != TopHalf)
12111 assert(TopHalf && BottomHalf &&
12112 "One half of the selector was all UNDEFs and the other was all the "
12113 "same value. This should have been addressed before this function.");
12116 BottomHalf->
isZero() ?
RHS->getOperand(0) :
LHS->getOperand(0),
12117 TopHalf->
isZero() ?
RHS->getOperand(1) :
LHS->getOperand(1));
12130 EVT VT = BasePtr.getValueType();
12134 SplatVal.getValueType() == VT) {
12140 if (Index.getOpcode() !=
ISD::ADD)
12146 Index = Index.getOperand(1);
12152 Index = Index.getOperand(0);
12167 Index = Index.getOperand(0);
12180 Index = Index.getOperand(0);
12265 MST1->isSimple() && MST1->getBasePtr() ==
Ptr &&
12268 MST1->getMemoryVT().getStoreSize()) ||
12272 CombineTo(MST1, MST1->getChain());
12289 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
12293 Value.getValueType().isInteger() &&
12294 (!isa<ConstantSDNode>(
Value) ||
12295 !cast<ConstantSDNode>(
Value)->isOpaque())) {
12296 APInt TruncDemandedBits =
12322 Value.getOperand(0).getValueType());
12333 auto *SST = cast<VPStridedStoreSDNode>(
N);
12336 if (
auto *CStride = dyn_cast<ConstantSDNode>(SST->getStride());
12337 CStride && CStride->getZExtValue() == EltVT.
getStoreSize()) {
12339 SST->getBasePtr(), SST->getOffset(), SST->getMask(),
12340 SST->getVectorLength(), SST->getMemoryVT(),
12341 SST->getMemOperand(), SST->getAddressingMode(),
12342 SST->isTruncatingStore(), SST->isCompressingStore());
12351 SDValue Passthru =
N->getOperand(2);
12354 bool HasPassthru = !Passthru.
isUndef();
12367 unsigned NumSelected = 0;
12369 for (
unsigned I = 0;
I < NumElmts; ++
I) {
12382 for (
unsigned Rest = NumSelected; Rest < NumElmts; ++Rest) {
12437 return CombineTo(
N, PassThru, MGT->
getChain());
12473 return CombineTo(
N, NewLd, NewLd.
getValue(1));
12477 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
12505 EVT DataVT =
Index.getValueType();
12513 auto *SLD = cast<VPStridedLoadSDNode>(
N);
12516 if (
auto *CStride = dyn_cast<ConstantSDNode>(SLD->getStride());
12517 CStride && CStride->getZExtValue() == EltVT.
getStoreSize()) {
12519 SLD->getAddressingMode(), SLD->getExtensionType(), SLD->getValueType(0),
12520 SDLoc(
N), SLD->getChain(), SLD->getBasePtr(), SLD->getOffset(),
12521 SLD->getMask(), SLD->getVectorLength(), SLD->getMemoryVT(),
12522 SLD->getMemOperand(), SLD->isExpandingLoad());
12523 return CombineTo(
N, NewLd, NewLd.
getValue(1));
12534 EVT VT =
N->getValueType(0);
12535 if (!
Cond.hasOneUse() ||
Cond.getScalarValueSizeInBits() != 1 ||
12544 bool AllAddOne =
true;
12545 bool AllSubOne =
true;
12547 for (
unsigned i = 0; i != Elts; ++i) {
12569 if (AllAddOne || AllSubOne) {
12605 if (
SDValue V = foldBoolSelectToLogic<VPMatchContext>(
N,
DL, DAG))
12615 EVT VT =
N->getValueType(0);
12621 if (
SDValue V = foldBoolSelectToLogic<EmptyMatchContext>(
N,
DL, DAG))
12647 bool isAbs =
false;
12666 AddToWorklist(Shift.
getNode());
12667 AddToWorklist(
Add.getNode());
12679 if (
SDValue FMinMax = combineMinNumMaxNum(
DL, VT, LHS, RHS, N1, N2,
CC))
12694 EVT NarrowVT =
LHS.getValueType();
12702 SetCCWidth != 1 && SetCCWidth < WideWidth &&
12718 if (
SDValue ABD = foldSelectToABD(LHS, RHS, N1, N2,
CC,
DL))
12748 (OpLHS == CondLHS || OpRHS == CondLHS))
12751 if (OpRHS.getOpcode() == CondRHS.getOpcode() &&
12754 CondLHS == OpLHS) {
12759 return Cond->getAPIntValue() ==
~Op->getAPIntValue();
12800 if (OpLHS == LHS) {
12816 return (!
Op && !
Cond) ||
12818 Cond->getAPIntValue() == (-
Op->getAPIntValue() - 1));
12849 if (SimplifySelectOps(
N, N1, N2))
12869 if (
SDValue V = foldVSelectOfConstants(
N))
12903 AddToWorklist(
SCC.getNode());
12907 if (
auto *SCCC = dyn_cast<ConstantSDNode>(
SCC.getNode()))
12908 return SCCC->isZero() ? N3 : N2;
12912 if (
SCC->isUndef())
12919 SCC.getOperand(1), N2, N3,
SCC.getOperand(2));
12926 if (SimplifySelectOps(
N, N2, N3))
12930 return SimplifySelectCC(
DL, N0, N1, N2, N3,
CC);
12938 N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BRCOND;
12941 EVT VT =
N->getValueType(0);
12942 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
12948 if (PreferSetCC && Combined.getOpcode() !=
ISD::SETCC) {
12949 SDValue NewSetCC = rebuildSetCC(Combined);
12977 A.getOperand(0) ==
B.getOperand(0);
12981 B.getOperand(0) ==
A;
12984 bool IsRotate =
false;
12987 if (IsAndWithShift(N0, N1)) {
12989 ShiftOrRotate = N1;
12990 }
else if (IsAndWithShift(N1, N0)) {
12992 ShiftOrRotate = N0;
12993 }
else if (IsRotateWithOp(N0, N1)) {
12996 ShiftOrRotate = N1;
12997 }
else if (IsRotateWithOp(N1, N0)) {
13000 ShiftOrRotate = N0;
13003 if (AndOrOp && ShiftOrRotate && ShiftOrRotate.hasOneUse() &&
13008 auto GetAPIntValue = [](
SDValue Op) -> std::optional<APInt> {
13011 if (CNode ==
nullptr)
13012 return std::nullopt;
13015 std::optional<APInt> AndCMask =
13016 IsRotate ? std::nullopt : GetAPIntValue(AndOrOp.
getOperand(1));
13017 std::optional<APInt> ShiftCAmt =
13018 GetAPIntValue(ShiftOrRotate.getOperand(1));
13022 if (ShiftCAmt && (IsRotate || AndCMask) && ShiftCAmt->ult(NumBits)) {
13023 unsigned ShiftOpc = ShiftOrRotate.getOpcode();
13025 bool CanTransform = IsRotate;
13026 if (!CanTransform) {
13028 CanTransform = *ShiftCAmt == (~*AndCMask).
popcount();
13030 CanTransform &= (*ShiftCAmt + AndCMask->popcount()) == NumBits;
13038 OpVT, ShiftOpc, ShiftCAmt->isPowerOf2(), *ShiftCAmt, AndCMask);
13040 if (CanTransform && NewShiftOpc != ShiftOpc) {
13042 DAG.
getNode(NewShiftOpc,
DL, OpVT, ShiftOrRotate.getOperand(0),
13043 ShiftOrRotate.getOperand(1));
13050 NumBits - ShiftCAmt->getZExtValue())
13051 :
APInt::getLowBitsSet(NumBits,
13052 NumBits - ShiftCAmt->getZExtValue());
13060 return DAG.
getSetCC(
DL, VT, NewAndOrOp, NewShiftOrRotate,
Cond);
13089 if (!
N.hasOneUse())
13092 if (!isa<LoadSDNode>(
N))
13118 unsigned Opcode =
N->getOpcode();
13120 EVT VT =
N->getValueType(0);
13123 "Expected EXTEND dag node in input!");
13164 unsigned Opcode =
N->getOpcode();
13166 EVT VT =
N->getValueType(0);
13169 "Expected EXTEND dag node in input!");
13174 if (isa<ConstantSDNode>(N0))
13175 return DAG.
getNode(Opcode,
DL, VT, N0);
13183 if (isa<ConstantSDNode>(Op1) && isa<ConstantSDNode>(Op2) &&
13194 unsigned FoldOpc = Opcode;
13217 for (
unsigned i = 0; i != NumElts; ++i) {
13219 if (
Op.isUndef()) {
13230 APInt C =
Op->getAsAPIntVal().zextOrTrunc(EVTBits);
13248 bool HasCopyToRegUses =
false;
13263 for (
unsigned i = 0; i != 2; ++i) {
13267 if (!isa<ConstantSDNode>(UseOp))
13281 HasCopyToRegUses =
true;
13284 if (HasCopyToRegUses) {
13285 bool BothLiveOut =
false;
13288 BothLiveOut =
true;
13295 return !ExtendNodes.
empty();
13305 for (
SDNode *SetCC : SetCCs) {
13308 for (
unsigned j = 0;
j != 2; ++
j) {
13310 if (SOp == OrigLoad)
13324 EVT DstVT =
N->getValueType(0);
13329 "Unexpected node type (not an extend)!");
13367 EVT SplitSrcVT = SrcVT;
13368 EVT SplitDstVT = DstVT;
13381 const unsigned NumSplits =
13388 for (
unsigned Idx = 0;
Idx < NumSplits;
Idx++) {
13407 AddToWorklist(NewChain.
getNode());
13409 CombineTo(
N, NewValue);
13415 ExtendSetCCUses(SetCCs, N0, NewValue, (
ISD::NodeType)
N->getOpcode());
13416 CombineTo(N0.
getNode(), Trunc, NewChain);
13424 EVT VT =
N->getValueType(0);
13425 EVT OrigVT =
N->getOperand(0).getValueType();
13447 EVT MemVT =
Load->getMemoryVT();
13468 Load->getChain(),
Load->getBasePtr(),
13469 Load->getMemoryVT(),
Load->getMemOperand());
13482 if (
SDValue(Load, 0).hasOneUse()) {
13486 Load->getValueType(0), ExtLoad);
13487 CombineTo(Load, Trunc, ExtLoad.
getValue(1));
13491 recursivelyDeleteUnusedNodes(N0.
getNode());
13500SDValue DAGCombiner::matchVSelectOpSizesWithSetCC(
SDNode *Cast) {
13501 unsigned CastOpcode = Cast->
getOpcode();
13505 "Unexpected opcode for vector select narrowing/widening");
13545 bool LegalOperations,
SDNode *
N,
13556 if ((LegalOperations || !LN0->
isSimple() ||
13567 Combiner.recursivelyDeleteUnusedNodes(LN0);
13580 bool NonNegZExt =
false) {
13587 "Unexpected load type or opcode");
13604 !cast<LoadSDNode>(N0)->isSimple()) &&
13608 bool DoXform =
true;
13621 Combiner.ExtendSetCCUses(SetCCs, N0, ExtLoad, ExtOpc);
13625 if (NoReplaceTrunc) {
13627 Combiner.recursivelyDeleteUnusedNodes(LN0);
13647 if ((LegalOperations || !cast<MaskedLoadSDNode>(N0)->
isSimple()) &&
13669 auto *ALoad = dyn_cast<AtomicSDNode>(N0);
13672 EVT MemoryVT = ALoad->getMemoryVT();
13681 EVT OrigVT = ALoad->getValueType(0);
13683 auto *NewALoad = cast<AtomicSDNode>(DAG.
getAtomic(
13685 ALoad->getBasePtr(), ALoad->getMemOperand()));
13686 NewALoad->setExtensionType(ExtLoadType);
13696 bool LegalOperations) {
13708 EVT VT =
N->getValueType(0);
13709 EVT XVT =
X.getValueType();
13725 return DAG.
getNode(ShiftOpcode,
DL, VT, NotX, ShiftAmount);
13739 EVT VT =
N->getValueType(0);
13749 if (VT.
isVector() && !LegalOperations &&
13768 if (SVT == MatchingVecType) {
13784 auto IsFreeToExtend = [&](
SDValue V) {
13792 cast<LoadSDNode>(V)->isSimple() &&
13806 if (
User->getOpcode() != ExtOpcode ||
User->getValueType(0) != VT)
13812 if (IsFreeToExtend(N00) && IsFreeToExtend(N01)) {
13832 SDValue ExtTrueVal = (SetCCWidth == 1)
13836 if (
SDValue SCC = SimplifySelectCC(
DL, N00, N01, ExtTrueVal, Zero,
CC,
true))
13848 return DAG.
getSelect(
DL, VT, SetCC, ExtTrueVal, Zero);
13857 EVT VT =
N->getValueType(0);
13861 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
13899 if (NarrowLoad.getNode() != N0.
getNode()) {
13900 CombineTo(N0.
getNode(), NarrowLoad);
13902 AddToWorklist(oye);
13910 unsigned OpBits =
Op.getScalarValueSizeInBits();
13916 if (OpBits == DestBits) {
13922 if (OpBits < DestBits) {
13931 Flags.setNoSignedWrap(
true);
13939 if (OpBits < DestBits)
13941 else if (OpBits > DestBits)
13961 if (
SDValue ExtLoad = CombineExtLoad(
N))
13996 bool NoReplaceTruncAnd = !N0.
hasOneUse();
14000 if (NoReplaceTruncAnd) {
14003 CombineTo(N0.
getNode(), TruncAnd);
14005 if (NoReplaceTrunc) {
14010 CombineTo(LN00, Trunc, ExtLoad.
getValue(1));
14029 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
14060 if (NewXor.getNode() == N0.
getNode()) {
14086 "Expected extend op");
14132 EVT VT =
N->getValueType(0);
14136 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
14167 APInt TruncatedBits =
14169 APInt(
Op.getScalarValueSizeInBits(), 0) :
14172 std::min(
Op.getScalarValueSizeInBits(),
14178 return ZExtOrTrunc;
14188 if (NarrowLoad.getNode() != N0.
getNode()) {
14189 CombineTo(N0.
getNode(), NarrowLoad);
14191 AddToWorklist(oye);
14199 if (
N->getFlags().hasNonNeg()) {
14207 if (OpBits == DestBits) {
14213 if (OpBits < DestBits) {
14223 Flags.setNoSignedWrap(
true);
14224 Flags.setNoUnsignedWrap(
true);
14236 AddToWorklist(
Op.getNode());
14240 return ZExtOrTrunc;
14246 AddToWorklist(
Op.getNode());
14282 if (
SDValue ExtLoad = CombineExtLoad(
N))
14302 bool DoXform =
true;
14306 auto *AndC = cast<ConstantSDNode>(N0.
getOperand(1));
14309 if (isAndLoadExtLoad(AndC, LN00, LoadResultTy, ExtVT))
14325 bool NoReplaceTruncAnd = !N0.
hasOneUse();
14329 if (NoReplaceTruncAnd) {
14332 CombineTo(N0.
getNode(), TruncAnd);
14334 if (NoReplaceTrunc) {
14339 CombineTo(LN00, Trunc, ExtLoad.
getValue(1));
14348 if (
SDValue ZExtLoad = CombineZExtLogicopShiftLoad(
N))
14364 if (!LegalOperations && VT.
isVector() &&
14396 if (
SDValue SCC = SimplifySelectCC(
14400 cast<CondCodeSDNode>(N0.
getOperand(2))->get(),
true))
14409 if (
auto *ShAmtC = dyn_cast<ConstantSDNode>(ShAmt)) {
14416 if (ShAmtC->getAPIntValue().ugt(KnownZeroBits)) {
14437 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
14461 EVT VT =
N->getValueType(0);
14495 if (NarrowLoad.getNode() != N0.
getNode()) {
14496 CombineTo(N0.
getNode(), NarrowLoad);
14498 AddToWorklist(oye);
14516 assert(isa<ConstantSDNode>(
Y) &&
"Expected constant to be folded!");
14532 bool DoXform =
true;
14545 CombineTo(
N, ExtLoad);
14546 if (NoReplaceTrunc) {
14548 recursivelyDeleteUnusedNodes(LN0);
14552 CombineTo(LN0, Trunc, ExtLoad.
getValue(1));
14566 if (!LegalOperations || TLI.
isLoadExtLegal(ExtType, VT, MemVT)) {
14570 CombineTo(
N, ExtLoad);
14572 recursivelyDeleteUnusedNodes(LN0);
14586 if (VT.
isVector() && !LegalOperations) {
14598 cast<CondCodeSDNode>(N0.
getOperand(2))->get());
14606 cast<CondCodeSDNode>(N0.
getOperand(2))->get());
14611 if (
SDValue SCC = SimplifySelectCC(
14614 cast<CondCodeSDNode>(N0.
getOperand(2))->get(),
true))
14628 unsigned Opcode =
N->getOpcode();
14631 EVT AssertVT = cast<VTSDNode>(N1)->getVT();
14635 AssertVT == cast<VTSDNode>(N0.
getOperand(1))->getVT())
14647 EVT BigA_AssertVT = cast<VTSDNode>(BigA.
getOperand(1))->getVT();
14648 EVT MinAssertVT = AssertVT.
bitsLT(BigA_AssertVT) ? AssertVT : BigA_AssertVT;
14662 EVT BigA_AssertVT = cast<VTSDNode>(BigA.
getOperand(1))->getVT();
14663 if (AssertVT.
bitsLT(BigA_AssertVT)) {
14677 Align AL = cast<AssertAlignSDNode>(
N)->getAlign();
14682 if (
auto *AAN = dyn_cast<AssertAlignSDNode>(N0))
14684 std::max(AL, AAN->getAlign()));
14694 unsigned AlignShift =
Log2(AL);
14699 if (LHSAlignShift >= AlignShift || RHSAlignShift >= AlignShift) {
14700 if (LHSAlignShift < AlignShift)
14702 if (RHSAlignShift < AlignShift)
14717 unsigned Opc =
N->getOpcode();
14721 EVT VT =
N->getValueType(0);
14731 unsigned ShAmt = 0;
14736 unsigned ShiftedOffset = 0;
14741 ExtVT = cast<VTSDNode>(
N->getOperand(1))->getVT();
14749 auto *LN = dyn_cast<LoadSDNode>(N0);
14750 auto *N1C = dyn_cast<ConstantSDNode>(
N->getOperand(1));
14756 uint64_t MemoryWidth = LN->getMemoryVT().getScalarSizeInBits();
14757 if (MemoryWidth <= ShAmt)
14768 LN->getExtensionType() != ExtType)
14772 auto AndC = dyn_cast<ConstantSDNode>(
N->getOperand(1));
14777 unsigned ActiveBits = 0;
14778 if (
Mask.isMask()) {
14779 ActiveBits =
Mask.countr_one();
14780 }
else if (
Mask.isShiftedMask(ShAmt, ActiveBits)) {
14781 ShiftedOffset = ShAmt;
14802 if (!
SRL.hasOneUse())
14807 auto *LN = dyn_cast<LoadSDNode>(
SRL.getOperand(0));
14808 auto *SRL1C = dyn_cast<ConstantSDNode>(
SRL.getOperand(1));
14815 ShAmt = SRL1C->getZExtValue();
14816 uint64_t MemoryWidth = LN->getMemoryVT().getSizeInBits();
14817 if (ShAmt >= MemoryWidth)
14844 isa<ConstantSDNode>(
Mask->getOperand(1))) {
14845 unsigned Offset, ActiveBits;
14846 const APInt& ShiftMask =
Mask->getConstantOperandAPInt(1);
14847 if (ShiftMask.
isMask()) {
14869 N0 =
SRL.getOperand(0);
14877 unsigned ShLeftAmt = 0;
14881 ShLeftAmt = N01->getZExtValue();
14887 if (!isa<LoadSDNode>(N0))
14894 !isLegalNarrowLdSt(LN0, ExtType, ExtVT, ShAmt))
14897 auto AdjustBigEndianShift = [&](
unsigned ShAmt) {
14898 unsigned LVTStoreBits =
14901 return LVTStoreBits - EVTStoreBits - ShAmt;
14906 unsigned PtrAdjustmentInBits =
14909 uint64_t PtrOff = PtrAdjustmentInBits / 8;
14915 AddToWorklist(NewPtr.
getNode());
14930 WorklistRemover DeadNodes(*
this);
14935 if (ShLeftAmt != 0) {
14947 if (ShiftedOffset != 0) {
14964 EVT VT =
N->getValueType(0);
14965 EVT ExtVT = cast<VTSDNode>(N1)->getVT();
14995 if ((N00Bits <= ExtVTBits ||
15011 if ((N00Bits == ExtVTBits ||
15012 (!IsZext && (N00Bits < ExtVTBits ||
15014 (!LegalOperations ||
15039 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
15046 if (
auto *ShAmt = dyn_cast<ConstantSDNode>(N0.
getOperand(1)))
15047 if (ShAmt->getAPIntValue().ule(VTBits - ExtVTBits)) {
15051 if (((VTBits - ExtVTBits) - ShAmt->getZExtValue()) < InSignBits)
15062 ExtVT == cast<LoadSDNode>(N0)->getMemoryVT() &&
15063 ((!LegalOperations && cast<LoadSDNode>(N0)->isSimple() &&
15066 auto *LN0 = cast<LoadSDNode>(N0);
15070 CombineTo(
N, ExtLoad);
15072 AddToWorklist(ExtLoad.
getNode());
15078 N0.
hasOneUse() && ExtVT == cast<LoadSDNode>(N0)->getMemoryVT() &&
15079 ((!LegalOperations && cast<LoadSDNode>(N0)->isSimple()) &&
15081 auto *LN0 = cast<LoadSDNode>(N0);
15085 CombineTo(
N, ExtLoad);
15093 if (ExtVT == Ld->getMemoryVT() && N0.
hasOneUse() &&
15097 VT,
DL, Ld->getChain(), Ld->getBasePtr(), Ld->getOffset(),
15098 Ld->getMask(), Ld->getPassThru(), ExtVT, Ld->getMemOperand(),
15099 Ld->getAddressingMode(),
ISD::SEXTLOAD, Ld->isExpandingLoad());
15100 CombineTo(
N, ExtMaskedLoad);
15107 if (
auto *GN0 = dyn_cast<MaskedGatherSDNode>(N0)) {
15108 if (
SDValue(GN0, 0).hasOneUse() && ExtVT == GN0->getMemoryVT() &&
15110 SDValue Ops[] = {GN0->getChain(), GN0->getPassThru(), GN0->getMask(),
15111 GN0->getBasePtr(), GN0->getIndex(), GN0->getScale()};
15114 DAG.
getVTList(VT, MVT::Other), ExtVT,
DL, Ops, GN0->getMemOperand(),
15117 CombineTo(
N, ExtLoad);
15119 AddToWorklist(ExtLoad.
getNode());
15142 (!LegalOperations ||
15156 bool LegalOperations) {
15157 unsigned InregOpcode =
N->getOpcode();
15161 EVT VT =
N->getValueType(0);
15163 Src.getValueType().getVectorElementType(),
15167 "Expected EXTEND_VECTOR_INREG dag node in input!");
15176 Src = Src.getOperand(0);
15177 if (Src.getValueType() != SrcVT)
15183 return DAG.
getNode(Opcode,
DL, VT, Src);
15188 EVT VT =
N->getValueType(0);
15213 EVT VT =
N->getValueType(0);
15234 unsigned NumSrcBits = In.getScalarValueSizeInBits();
15236 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
15257 unsigned NumSrcBits = In.getScalarValueSizeInBits();
15259 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
15280 unsigned NumSrcBits = In.getScalarValueSizeInBits();
15282 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
15305 auto AllowedTruncateSat = [&](
unsigned Opc,
EVT SrcVT,
EVT VT) ->
bool {
15317 }
else if (Src.getOpcode() ==
ISD::UMIN) {
15331 EVT VT =
N->getValueType(0);
15346 return SaturatedTR;
15373 EVT ExtVT = cast<VTSDNode>(ExtVal)->getVT();
15394 if (LegalTypes && !LegalOperations && VT.
isScalarInteger() && VT != MVT::i1 &&
15396 EVT TrTy =
N->getValueType(0);
15401 if (Src.getOpcode() ==
ISD::SRL && Src.getOperand(0)->hasOneUse()) {
15404 Src = Src.getOperand(0);
15411 EVT VecTy = Src.getOperand(0).getValueType();
15412 EVT ExTy = Src.getValueType();
15416 auto NewEltCnt = EltCnt * SizeRatio;
15421 SDValue EltNo = Src->getOperand(1);
15422 if (isa<ConstantSDNode>(EltNo) &&
isTypeLegal(NVT)) {
15424 int Index = isLE ? (Elt * SizeRatio + EltOffset)
15425 : (Elt * SizeRatio + (SizeRatio - 1) - EltOffset);
15436 if (!LegalOperations ||
15459 AddToWorklist(Amt.
getNode());
15508 if (BuildVectEltTy == TruncVecEltTy) {
15512 unsigned TruncEltOffset = BuildVecNumElts / TruncVecNumElts;
15513 unsigned FirstElt = isLE ? 0 : (TruncEltOffset - 1);
15515 assert((BuildVecNumElts % TruncVecNumElts) == 0 &&
15516 "Invalid number of elements");
15519 for (
unsigned i = FirstElt, e = BuildVecNumElts; i <
e;
15520 i += TruncEltOffset)
15530 if (
SDValue Reduced = reduceLoadWidth(
N))
15536 auto *LN0 = cast<LoadSDNode>(N0);
15553 unsigned NumDefs = 0;
15557 if (!
X.isUndef()) {
15568 X.getValueType().getVectorElementCount()));
15574 if (NumDefs == 1) {
15575 assert(
V.getNode() &&
"The single defined operand is empty!");
15577 for (
unsigned i = 0, e = VTs.
size(); i != e; ++i) {
15583 AddToWorklist(
NV.getNode());
15598 (!LegalOperations ||
15626 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
15640 if (!LegalOperations && N0.
hasOneUse() &&
15673 if (!LegalOperations && N0.
hasOneUse() &&
15709 !LD1->hasOneUse() || !LD2->hasOneUse() ||
15710 LD1->getAddressSpace() != LD2->getAddressSpace())
15713 unsigned LD1Fast = 0;
15714 EVT LD1VT = LD1->getValueType(0);
15719 *LD1->getMemOperand(), &LD1Fast) && LD1Fast)
15720 return DAG.
getLoad(VT,
SDLoc(
N), LD1->getChain(), LD1->getBasePtr(),
15721 LD1->getPointerInfo(), LD1->getAlign());
15736 EVT VT =
N->getValueType(0);
15773 auto IsBitCastOrFree = [&TLI, FPOpcode](
SDValue Op,
EVT VT) {
15787 IsBitCastOrFree(LogicOp0, VT)) {
15790 NumFPLogicOpsConv++;
15801 EVT VT =
N->getValueType(0);
15817 cast<BuildVectorSDNode>(N0)->isConstant())
15818 return ConstantFoldBITCASTofBUILD_VECTOR(N0.
getNode(),
15826 if (!LegalOperations ||
15832 if (
C.getNode() !=
N)
15845 auto IsFreeBitcast = [VT](
SDValue V) {
15847 V.getOperand(0).getValueType() == VT) ||
15868 ((!LegalOperations && cast<LoadSDNode>(N0)->isSimple()) ||
15882 if (
SDValue V = foldBitcastedFPLogic(
N, DAG, TLI))
15902 AddToWorklist(NewConv.
getNode());
15905 if (N0.
getValueType() == MVT::ppcf128 && !LegalTypes) {
15912 AddToWorklist(FlipBit.
getNode());
15919 AddToWorklist(
Hi.getNode());
15921 AddToWorklist(FlipBit.
getNode());
15925 AddToWorklist(FlipBits.
getNode());
15955 AddToWorklist(
X.getNode());
15959 if (OrigXWidth < VTWidth) {
15961 AddToWorklist(
X.getNode());
15962 }
else if (OrigXWidth > VTWidth) {
15967 X.getValueType(),
X,
15969 X.getValueType()));
15970 AddToWorklist(
X.getNode());
15972 AddToWorklist(
X.getNode());
15975 if (N0.
getValueType() == MVT::ppcf128 && !LegalTypes) {
15978 AddToWorklist(Cst.
getNode());
15980 AddToWorklist(
X.getNode());
15982 AddToWorklist(XorResult.
getNode());
15986 SDLoc(XorResult)));
15987 AddToWorklist(XorResult64.
getNode());
15991 AddToWorklist(FlipBit.
getNode());
15994 AddToWorklist(FlipBits.
getNode());
16000 AddToWorklist(
X.getNode());
16005 AddToWorklist(Cst.
getNode());
16013 if (
SDValue CombineLD = CombineConsecutiveLoads(N0.
getNode(), VT))
16036 auto PeekThroughBitcast = [&](
SDValue Op) {
16038 Op.getOperand(0).getValueType() == VT)
16057 for (
int i = 0; i != MaskScale; ++i)
16058 NewMask.
push_back(M < 0 ? -1 : M * MaskScale + i);
16063 return LegalShuffle;
16070 EVT VT =
N->getValueType(0);
16071 return CombineConsecutiveLoads(
N, VT);
16098 bool AllowMultipleMaybePoisonOperands =
16132 bool HadMaybePoisonOperands = !MaybePoisonOperands.
empty();
16133 bool IsNewMaybePoisonOperand = MaybePoisonOperands.
insert(
Op).second;
16134 if (IsNewMaybePoisonOperand)
16135 MaybePoisonOperandNumbers.
push_back(OpNo);
16136 if (!HadMaybePoisonOperands)
16138 if (IsNewMaybePoisonOperand && !AllowMultipleMaybePoisonOperands) {
16147 for (
unsigned OpNo : MaybePoisonOperandNumbers) {
16158 SDValue MaybePoisonOperand =
N->getOperand(0).getOperand(OpNo);
16167 FrozenMaybePoisonOperand.
getOperand(0) == FrozenMaybePoisonOperand) {
16171 MaybePoisonOperand);
16181 N0 =
N->getOperand(0);
16193 if (
auto *SVN = dyn_cast<ShuffleVectorSDNode>(N0)) {
16202 "Can't create node that may be undef/poison!");
16209ConstantFoldBITCASTofBUILD_VECTOR(
SDNode *BV,
EVT DstEltVT) {
16213 if (SrcEltVT == DstEltVT)
return SDValue(BV, 0);
16220 if (SrcBitSize == DstBitSize) {
16225 if (
Op.getValueType() != SrcEltVT)
16228 AddToWorklist(Ops.
back().getNode());
16242 BV = ConstantFoldBITCASTofBUILD_VECTOR(BV, IntVT).getNode();
16250 SDNode *Tmp = ConstantFoldBITCASTofBUILD_VECTOR(BV, TmpVT).getNode();
16253 return ConstantFoldBITCASTofBUILD_VECTOR(Tmp, DstEltVT);
16261 auto *BVN = cast<BuildVectorSDNode>(BV);
16267 if (!BVN->getConstantRawBits(IsLE, DstBitSize, RawBits, UndefElements))
16272 for (
unsigned I = 0, E = RawBits.
size();
I != E; ++
I) {
16273 if (UndefElements[
I])
16289 N->getFlags().hasAllowContract();
16294 return Options.NoInfsFPMath ||
N->getFlags().hasNoInfs();
16298template <
class MatchContextClass>
16302 EVT VT =
N->getValueType(0);
16304 MatchContextClass matcher(DAG, TLI,
N);
16307 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
16312 bool HasFMAD = !UseVP && (LegalOperations && TLI.
isFMADLegal(DAG,
N));
16316 (!LegalOperations || matcher.isOperationLegalOrCustom(
ISD::FMA, VT)) &&
16320 if (!HasFMAD && !HasFMA)
16324 Options.UnsafeFPMath || HasFMAD);
16326 if (!AllowFusionGlobally && !
N->getFlags().hasAllowContract())
16352 return AllowFusionGlobally ||
N->getFlags().hasAllowContract();
16363 return matcher.getNode(PreferredFusedOpcode, SL, VT, N0.
getOperand(0),
16370 return matcher.getNode(PreferredFusedOpcode, SL, VT, N1.
getOperand(0),
16382 bool CanReassociate =
16383 Options.UnsafeFPMath ||
N->getFlags().hasAllowReassociation();
16384 if (CanReassociate) {
16389 }
else if (isFusedOp(N1) && N1.
hasOneUse()) {
16395 while (E && isFusedOp(TmpFMA) && TmpFMA.
hasOneUse()) {
16420 PreferredFusedOpcode, SL, VT,
16434 PreferredFusedOpcode, SL, VT,
16446 return matcher.getNode(
16447 PreferredFusedOpcode, SL, VT,
X,
Y,
16448 matcher.getNode(PreferredFusedOpcode, SL, VT,
16452 if (isFusedOp(N0)) {
16473 return matcher.getNode(
16474 PreferredFusedOpcode, SL, VT,
16477 matcher.getNode(PreferredFusedOpcode, SL, VT,
16483 if (isFusedOp(N00)) {
16497 if (isFusedOp(N1)) {
16518 if (isFusedOp(N10)) {
16535template <
class MatchContextClass>
16539 EVT VT =
N->getValueType(0);
16541 MatchContextClass matcher(DAG, TLI,
N);
16544 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
16549 bool HasFMAD = !UseVP && (LegalOperations && TLI.
isFMADLegal(DAG,
N));
16553 (!LegalOperations || matcher.isOperationLegalOrCustom(
ISD::FMA, VT)) &&
16557 if (!HasFMAD && !HasFMA)
16562 Options.UnsafeFPMath || HasFMAD);
16565 if (!AllowFusionGlobally && !
N->getFlags().hasAllowContract())
16574 bool NoSignedZero =
Options.NoSignedZerosFPMath ||
Flags.hasNoSignedZeros();
16581 return AllowFusionGlobally ||
N->getFlags().hasAllowContract();
16587 return matcher.getNode(PreferredFusedOpcode, SL, VT, XY.
getOperand(0),
16598 return matcher.getNode(
16599 PreferredFusedOpcode, SL, VT,
16600 matcher.getNode(
ISD::FNEG, SL, VT, YZ.getOperand(0)),
16601 YZ.getOperand(1),
X);
16611 if (
SDValue V = tryToFoldXSubYZ(N0, N1))
16614 if (
SDValue V = tryToFoldXYSubZ(N0, N1))
16618 if (
SDValue V = tryToFoldXYSubZ(N0, N1))
16621 if (
SDValue V = tryToFoldXSubYZ(N0, N1))
16630 return matcher.
getNode(PreferredFusedOpcode, SL, VT,
16631 matcher.getNode(
ISD::FNEG, SL, VT, N00), N01,
16632 matcher.getNode(
ISD::FNEG, SL, VT, N1));
16645 PreferredFusedOpcode, SL, VT,
16648 matcher.getNode(
ISD::FNEG, SL, VT, N1));
16661 PreferredFusedOpcode, SL, VT,
16685 PreferredFusedOpcode, SL, VT,
16709 PreferredFusedOpcode, SL, VT,
16718 return Options.UnsafeFPMath ||
N->getFlags().hasAllowReassociation();
16732 bool CanFuse =
Options.UnsafeFPMath ||
N->getFlags().hasAllowContract();
16735 if (CanFuse && isFusedOp(N0) &&
16736 isContractableAndReassociableFMUL(N0.
getOperand(2)) &&
16738 return matcher.getNode(
16740 matcher.
getNode(PreferredFusedOpcode, SL, VT,
16748 if (CanFuse && isFusedOp(N1) &&
16749 isContractableAndReassociableFMUL(N1.
getOperand(2)) &&
16754 PreferredFusedOpcode, SL, VT,
16757 matcher.
getNode(PreferredFusedOpcode, SL, VT,
16758 matcher.getNode(
ISD::FNEG, SL, VT, N20), N21, N0));
16763 if (isFusedOp(N0) && N0->
hasOneUse()) {
16767 if (isContractableAndReassociableFMUL(N020) &&
16773 PreferredFusedOpcode, SL, VT,
16776 matcher.getNode(
ISD::FNEG, SL, VT, N1)));
16789 if (isFusedOp(N00)) {
16791 if (isContractableAndReassociableFMUL(N002) &&
16795 PreferredFusedOpcode, SL, VT,
16799 PreferredFusedOpcode, SL, VT,
16802 matcher.getNode(
ISD::FNEG, SL, VT, N1)));
16812 if (isContractableAndReassociableFMUL(N120) &&
16818 PreferredFusedOpcode, SL, VT,
16822 PreferredFusedOpcode, SL, VT,
16840 if (isContractableAndReassociableFMUL(N102) &&
16846 PreferredFusedOpcode, SL, VT,
16851 PreferredFusedOpcode, SL, VT,
16865SDValue DAGCombiner::visitFMULForFMADistributiveCombine(
SDNode *
N) {
16868 EVT VT =
N->getValueType(0);
16889 bool HasFMAD =
Options.UnsafeFPMath &&
16893 if (!HasFMAD && !HasFMA)
16905 if (
C->isExactlyValue(+1.0))
16906 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
16908 if (
C->isExactlyValue(-1.0))
16909 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
16916 if (
SDValue FMA = FuseFADD(N0, N1))
16918 if (
SDValue FMA = FuseFADD(N1, N0))
16928 if (C0->isExactlyValue(+1.0))
16929 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
16932 if (C0->isExactlyValue(-1.0))
16933 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
16938 if (C1->isExactlyValue(+1.0))
16939 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
16941 if (C1->isExactlyValue(-1.0))
16942 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
16949 if (
SDValue FMA = FuseFSUB(N0, N1))
16951 if (
SDValue FMA = FuseFSUB(N1, N0))
16961 if (
SDValue Fused = visitFADDForFMACombine<VPMatchContext>(
N)) {
16963 AddToWorklist(Fused.getNode());
16974 EVT VT =
N->getValueType(0);
16988 if (N0CFP && !N1CFP)
16993 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
16998 if (N1C && N1C->
isZero())
17002 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17008 N1, DAG, LegalOperations, ForCodeSize))
17014 N0, DAG, LegalOperations, ForCodeSize))
17021 return C &&
C->isExactlyValue(-2.0);
17025 if (isFMulNegTwo(N0)) {
17031 if (isFMulNegTwo(N1)) {
17042 if ((
Options.NoNaNsFPMath ||
Flags.hasNoNaNs()) && AllowNewConst) {
17056 (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros())) &&
17074 if (CFP01 && !CFP00 && N0.
getOperand(0) == N1) {
17095 if (CFP11 && !CFP10 && N1.
getOperand(0) == N0) {
17143 VT, N0, N1, Flags))
17148 if (
SDValue Fused = visitFADDForFMACombine<EmptyMatchContext>(
N)) {
17150 AddToWorklist(Fused.getNode());
17160 EVT VT =
N->getValueType(0);
17161 EVT ChainVT =
N->getValueType(1);
17168 N1, DAG, LegalOperations, ForCodeSize)) {
17170 {Chain, N0, NegN1});
17176 N0, DAG, LegalOperations, ForCodeSize)) {
17178 {Chain, N1, NegN0});
17188 EVT VT =
N->getValueType(0);
17203 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
17206 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17210 if (N1CFP && N1CFP->
isZero()) {
17212 Flags.hasNoSignedZeros()) {
17224 if (N0CFP && N0CFP->
isZero()) {
17226 (
Options.NoSignedZerosFPMath ||
Flags.hasNoSignedZeros())) {
17243 (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros())) &&
17259 if (
SDValue Fused = visitFSUBForFMACombine<EmptyMatchContext>(
N)) {
17260 AddToWorklist(Fused.getNode());
17283 EVT VT =
N->getValueType(0);
17286 std::optional<int> Mantissa;
17287 auto GetConstAndPow2Ops = [&](
unsigned ConstOpIdx) {
17288 if (ConstOpIdx == 1 &&
N->getOpcode() ==
ISD::FDIV)
17292 Pow2Op =
N->getOperand(1 - ConstOpIdx);
17305 if (CFP ==
nullptr)
17308 const APFloat &APF = CFP->getValueAPF();
17316 int CurExp =
ilogb(APF);
17319 N->getOpcode() ==
ISD::FMUL ? CurExp : (CurExp - MaxExpChange);
17322 N->getOpcode() ==
ISD::FDIV ? CurExp : (CurExp + MaxExpChange);
17330 Mantissa = ThisMantissa;
17332 return *Mantissa == ThisMantissa && ThisMantissa > 0;
17339 if (!GetConstAndPow2Ops(0) && !GetConstAndPow2Ops(1))
17368 NewIntVT, DAG.
getBitcast(NewIntVT, ConstOp), Shift);
17377 EVT VT =
N->getValueType(0);
17397 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
17400 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17403 if (
Options.UnsafeFPMath ||
Flags.hasAllowReassociation()) {
17429 VT, N0, N1, Flags))
17463 if (
Flags.hasNoNaNs() &&
Flags.hasNoSignedZeros() &&
17471 auto TrueOpnd = dyn_cast<ConstantFPSDNode>(
Select.getOperand(1));
17472 auto FalseOpnd = dyn_cast<ConstantFPSDNode>(
Select.getOperand(2));
17474 if (TrueOpnd && FalseOpnd &&
17476 isa<ConstantFPSDNode>(
Cond.getOperand(1)) &&
17477 cast<ConstantFPSDNode>(
Cond.getOperand(1))->isExactlyValue(0.0)) {
17495 if (TrueOpnd->isExactlyValue(-1.0) && FalseOpnd->isExactlyValue(1.0) &&
17499 if (TrueOpnd->isExactlyValue(1.0) && FalseOpnd->isExactlyValue(-1.0))
17508 if (
SDValue Fused = visitFMULForFMADistributiveCombine(
N)) {
17509 AddToWorklist(Fused.getNode());
17515 if (
SDValue R = combineFMulOrFDivWithIntPow2(
N))
17521template <
class MatchContextClass>
SDValue DAGCombiner::visitFMA(
SDNode *
N) {
17527 EVT VT =
N->getValueType(0);
17532 MatchContextClass matcher(DAG, TLI,
N);
17557 if (N0CFP && N0CFP->
isZero())
17559 if (N1CFP && N1CFP->
isZero())
17567 return matcher.getNode(
ISD::FADD,
DL, VT, N0, N2);
17572 return matcher.getNode(
ISD::FMA,
DL, VT, N1, N0, N2);
17574 bool CanReassociate =
17575 Options.UnsafeFPMath ||
N->getFlags().hasAllowReassociation();
17576 if (CanReassociate) {
17581 return matcher.getNode(
17590 return matcher.getNode(
17600 return matcher.getNode(
ISD::FADD,
DL, VT, N0, N2);
17605 AddToWorklist(RHSNeg.
getNode());
17606 return matcher.getNode(
ISD::FADD,
DL, VT, N2, RHSNeg);
17620 if (CanReassociate) {
17622 if (N1CFP && N0 == N2) {
17640 SDValue(
N, 0), DAG, LegalOperations, ForCodeSize))
17649 EVT VT =
N->getValueType(0);
17672 if (LegalDAG || (!UnsafeMath && !
Flags.hasAllowReciprocal()))
17676 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
17687 unsigned NumElts = 1;
17688 EVT VT =
N->getValueType(0);
17692 if (!MinUses || (N1->
use_size() * NumElts) < MinUses)
17698 for (
auto *U : N1->
users()) {
17699 if (
U->getOpcode() ==
ISD::FDIV &&
U->getOperand(1) == N1) {
17701 if (
U->getOperand(1).getOpcode() ==
ISD::FSQRT &&
17702 U->getOperand(0) ==
U->getOperand(1).getOperand(0) &&
17703 U->getFlags().hasAllowReassociation() &&
17704 U->getFlags().hasNoSignedZeros())
17709 if (UnsafeMath ||
U->getFlags().hasAllowReciprocal())
17716 if ((
Users.size() * NumElts) < MinUses)
17724 for (
auto *U :
Users) {
17725 SDValue Dividend =
U->getOperand(0);
17726 if (Dividend != FPOne) {
17728 Reciprocal, Flags);
17729 CombineTo(U, NewNode);
17730 }
else if (U != Reciprocal.
getNode()) {
17733 CombineTo(U, Reciprocal);
17742 EVT VT =
N->getValueType(0);
17757 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
17760 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17777 (
Options.UnsafeFPMath ||
Flags.hasAllowReciprocal()))) &&
17778 (!LegalOperations ||
17788 if (
Options.UnsafeFPMath ||
Flags.hasAllowReciprocal()) {
17828 A =
Y.getOperand(0);
17837 if (
SDValue Rsqrt = buildRsqrtEstimate(AAZ, Flags))
17841 recursivelyDeleteUnusedNodes(AAZ.
getNode());
17849 AddToWorklist(Div.
getNode());
17857 if (
SDValue RV = BuildDivEstimate(N0, N1, Flags))
17862 if ((
Options.NoSignedZerosFPMath ||
Flags.hasNoSignedZeros()) &&
17863 (
Options.UnsafeFPMath ||
Flags.hasAllowReassociation()))
17883 if (
SDValue R = combineFMulOrFDivWithIntPow2(
N))
17892 EVT VT =
N->getValueType(0);
17904 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17914 bool NeedsCopySign =
17938 if (!
Flags.hasApproximateFuncs() ||
17951 return buildSqrtEstimate(N0, Flags);
17966 if (YTy == MVT::f128)
17985 EVT VT =
N->getValueType(0);
17996 if (!
V.isNegative()) {
18050 EVT VT =
N->getValueType(0);
18060 if (!
Flags.hasNoSignedZeros() || !
Flags.hasNoInfs() || !
Flags.hasNoNaNs() ||
18061 !
Flags.hasApproximateFuncs())
18080 if (ExponentIs025 || ExponentIs075) {
18091 if ((!
Flags.hasNoSignedZeros() && ExponentIs025) || !
Flags.hasNoInfs() ||
18092 !
Flags.hasApproximateFuncs())
18125 EVT VT =
N->getValueType(0);
18146 EVT VT =
N->getValueType(0);
18194 EVT VT =
N->getValueType(0);
18232 EVT VT =
N->getValueType(0);
18238 EVT SrcVT = Src.getValueType();
18253 unsigned ActualSize = std::min(InputSize, OutputSize);
18262 return DAG.
getNode(ExtOp,
DL, VT, Src);
18273 EVT VT =
N->getValueType(0);
18289 EVT VT =
N->getValueType(0);
18305 EVT VT =
N->getValueType(0);
18324 EVT VT =
N->getValueType(0);
18337 const bool NIsTrunc =
N->getConstantOperandVal(1) == 1;
18375 AddToWorklist(Tmp.
getNode());
18379 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
18387 EVT VT =
N->getValueType(0);
18391 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
18411 if (
In.getValueType() == VT)
return In;
18425 CombineTo(
N, ExtLoad);
18434 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
18442 EVT VT =
N->getValueType(0);
18453 EVT VT =
N->getValueType(0);
18487 EVT VT =
N->getValueType(0);
18498 EVT VT =
N->getValueType(0);
18515 N->getFlags().hasNoSignedZeros()) && N0.
hasOneUse()) {
18520 if (
SDValue Cast = foldSignChangeInBitcast(
N))
18529 EVT VT =
N->getValueType(0);
18531 unsigned Opc =
N->getOpcode();
18553 return PropagatesNaN ?
N->getOperand(1) :
N->getOperand(0);
18562 if (IsMin == AF.
isNegative() && (!PropagatesNaN ||
Flags.hasNoNaNs()))
18563 return N->getOperand(1);
18569 if (IsMin != AF.
isNegative() && (PropagatesNaN ||
Flags.hasNoNaNs()))
18570 return N->getOperand(0);
18574 if (
SDValue SD = reassociateReduction(
18578 Opc,
SDLoc(
N), VT, N0, N1, Flags))
18586 EVT VT =
N->getValueType(0);
18595 return N->getOperand(0);
18602 if (
SDValue Cast = foldSignChangeInBitcast(
N))
18635 bool Updated =
false;
18647 return True || False;
18651 if (!IsAlwaysTrueOrFalse(
Cond, S1C)) {
18658 S1 =
S1->getOperand(0);
18690 if (
SDValue NewN1 = rebuildSetCC(N1))
18692 ChainHandle.getValue(), NewN1, N2,
N->getFlags());
18701 (
N.getOperand(0).hasOneUse() &&
18702 N.getOperand(0).getOpcode() ==
ISD::SRL))) {
18705 N =
N.getOperand(0);
18754 SDValue Tmp = visitXOR(
N.getNode());
18761 N = XORHandle.getValue();
18773 bool Equal =
false;
18778 Op0 =
N->getOperand(0);
18779 Op1 =
N->getOperand(1);
18783 EVT SetCCVT =
N.getValueType();
18803 SDValue CondLHS =
N->getOperand(2), CondRHS =
N->getOperand(3);
18813 CondLHS, CondRHS,
CC->get(),
SDLoc(
N),
18831 if (LD->isIndexed())
18833 EVT VT = LD->getMemoryVT();
18836 Ptr = LD->getBasePtr();
18837 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
18838 if (ST->isIndexed())
18840 EVT VT = ST->getMemoryVT();
18843 Ptr = ST->getBasePtr();
18846 if (LD->isIndexed())
18848 EVT VT = LD->getMemoryVT();
18852 Ptr = LD->getBasePtr();
18855 if (ST->isIndexed())
18857 EVT VT = ST->getMemoryVT();
18861 Ptr = ST->getBasePtr();
18875bool DAGCombiner::CombineToPreIndexedLoadStore(
SDNode *
N) {
18879 bool IsLoad =
true;
18880 bool IsMasked =
false;
18902 bool Swapped =
false;
18903 if (isa<ConstantSDNode>(BasePtr)) {
18922 if (isa<FrameIndexSDNode>(BasePtr) || isa<RegisterSDNode>(BasePtr))
18927 SDValue Val = IsMasked ? cast<MaskedStoreSDNode>(
N)->getValue()
18928 : cast<StoreSDNode>(
N)->getValue();
18931 if (Val == BasePtr)
18949 if (isa<ConstantSDNode>(
Offset))
18967 if (!isa<ConstantSDNode>(Op1)) {
18985 bool RealUse =
false;
19021 WorklistRemover DeadNodes(*
this);
19030 deleteAndRecombine(
N);
19036 for (
unsigned i = 0, e = OtherUses.
size(); i != e; ++i) {
19037 unsigned OffsetIdx = 1;
19038 if (OtherUses[i]->getOperand(OffsetIdx).
getNode() ==
BasePtr.getNode())
19041 BasePtr.getNode() &&
"Expected BasePtr operand");
19054 auto *CN = cast<ConstantSDNode>(OtherUses[i]->getOperand(OffsetIdx));
19055 const APInt &Offset0 = CN->getAPIntValue();
19057 int X0 = (OtherUses[i]->getOpcode() ==
ISD::SUB && OffsetIdx == 1) ? -1 : 1;
19058 int Y0 = (OtherUses[i]->getOpcode() ==
ISD::SUB && OffsetIdx == 0) ? -1 : 1;
19064 APInt CNV = Offset0;
19065 if (X0 < 0) CNV = -CNV;
19066 if (X1 * Y0 * Y1 < 0) CNV = CNV + Offset1;
19067 else CNV = CNV - Offset1;
19079 deleteAndRecombine(OtherUses[i]);
19084 deleteAndRecombine(
Ptr.getNode());
19085 AddToWorklist(
Result.getNode());
19106 if (isa<FrameIndexSDNode>(BasePtr) || isa<RegisterSDNode>(BasePtr))
19116 if (isa<MemSDNode>(
User)) {
19117 bool IsLoad =
true;
19118 bool IsMasked =
false;
19121 IsMasked, OtherPtr, TLI)) {
19147 IsMasked,
Ptr, TLI) ||
19181bool DAGCombiner::CombineToPostIndexedLoadStore(
SDNode *
N) {
19185 bool IsLoad =
true;
19186 bool IsMasked =
false;
19207 ++PostIndexedNodes;
19211 WorklistRemover DeadNodes(*
this);
19220 deleteAndRecombine(
N);
19224 Result.getValue(IsLoad ? 1 : 0));
19225 deleteAndRecombine(
Op);
19240 !cast<ConstantSDNode>(Inc)->isOpaque()) &&
19241 "Cannot split out indexing using opaque target constants");
19259 EVT STMemType =
ST->getMemoryVT();
19260 if (STType == STMemType)
19282 EVT LDMemType =
LD->getMemoryVT();
19283 EVT LDType =
LD->getValueType(0);
19285 "Attempting to extend value of non-matching type");
19286 if (LDType == LDMemType)
19289 switch (
LD->getExtensionType()) {
19325 if (!BasePtrST.equalBaseIndex(BasePtrLD, DAG,
Offset))
19328 GatherAllAliases(Store, Chain, Aliases);
19329 if (Aliases.
empty() ||
19330 (Aliases.
size() == 1 && Aliases.
front().getNode() == Store))
19339 if (BasePtrST.equalBaseIndex(BasePtrLD, DAG,
Offset))
19355 if (!ST || !
ST->isSimple() ||
ST->getAddressSpace() !=
LD->getAddressSpace())
19358 EVT LDType =
LD->getValueType(0);
19359 EVT LDMemType =
LD->getMemoryVT();
19360 EVT STMemType =
ST->getMemoryVT();
19361 EVT STType =
ST->getValue().getValueType();
19385 int64_t OrigOffset =
Offset;
19398 STCoversLD = (
Offset == 0) && LdMemSize == StMemSize;
19404 if (
LD->isIndexed()) {
19411 return CombineTo(LD, Ops, 3);
19413 return CombineTo(LD, Val, Chain);
19420 if (
Offset == 0 && LDType == STType && STMemType == LDMemType) {
19423 return ReplaceLd(LD,
ST->getValue(), Chain);
19431 SDLoc(ST), STType);
19433 return ReplaceLd(LD, Val, Chain);
19451 if (
LD->getBasePtr().isUndef() ||
Offset != 0)
19456 if (!getTruncatedStoreValue(ST, Val))
19460 if (STMemType != LDMemType) {
19468 if (!extendLoadedValueToExtension(LD, Val))
19470 return ReplaceLd(LD, Val, Chain);
19475 deleteAndRecombine(Val.
getNode());
19488 if (
LD->isSimple()) {
19489 if (
N->getValueType(1) == MVT::Other) {
19491 if (!
N->hasAnyUseOfValue(0)) {
19499 dbgs() <<
"\nWith chain: "; Chain.
dump(&DAG);
19501 WorklistRemover DeadNodes(*
this);
19503 AddUsersToWorklist(Chain.
getNode());
19504 if (
N->use_empty())
19505 deleteAndRecombine(
N);
19511 assert(
N->getValueType(2) == MVT::Other &&
"Malformed indexed loads?");
19519 if (!
N->hasAnyUseOfValue(0) && (CanSplitIdx || !
N->hasAnyUseOfValue(1))) {
19522 if (
N->hasAnyUseOfValue(1) && CanSplitIdx) {
19523 Index = SplitIndexingFromLoad(LD);
19526 AddUsersToWorklist(
N);
19530 dbgs() <<
"\nWith: ";
Undef.dump(&DAG);
19531 dbgs() <<
" and 2 other values\n");
19532 WorklistRemover DeadNodes(*
this);
19536 deleteAndRecombine(
N);
19544 if (
auto V = ForwardStoreValueToDirectLoad(LD))
19551 if (*Alignment >
LD->getAlign() &&
19552 isAligned(*Alignment,
LD->getSrcValueOffset())) {
19554 LD->getExtensionType(),
SDLoc(
N),
LD->getValueType(0), Chain,
Ptr,
19555 LD->getPointerInfo(),
LD->getMemoryVT(), *Alignment,
19556 LD->getMemOperand()->getFlags(),
LD->getAAInfo());
19564 if (
LD->isUnindexed()) {
19566 SDValue BetterChain = FindBetterChain(LD, Chain);
19569 if (Chain != BetterChain) {
19575 BetterChain,
Ptr,
LD->getMemOperand());
19578 LD->getValueType(0),
19579 BetterChain,
Ptr,
LD->getMemoryVT(),
19580 LD->getMemOperand());
19585 MVT::Other, Chain, ReplLoad.
getValue(1));
19588 return CombineTo(
N, ReplLoad.
getValue(0), Token);
19593 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
19598 if (SliceUpLoad(
N))
19618struct LoadedSlice {
19622 bool ForCodeSize =
false;
19625 unsigned Loads = 0;
19626 unsigned Truncates = 0;
19627 unsigned CrossRegisterBanksCopies = 0;
19628 unsigned ZExts = 0;
19629 unsigned Shift = 0;
19631 explicit Cost(
bool ForCodeSize) : ForCodeSize(ForCodeSize) {}
19634 Cost(
const LoadedSlice &LS,
bool ForCodeSize)
19635 : ForCodeSize(ForCodeSize), Loads(1) {
19636 EVT TruncType =
LS.Inst->getValueType(0);
19637 EVT LoadedType =
LS.getLoadedType();
19638 if (TruncType != LoadedType &&
19639 !
LS.DAG->getTargetLoweringInfo().isZExtFree(LoadedType, TruncType))
19647 void addSliceGain(
const LoadedSlice &LS) {
19656 if (
LS.canMergeExpensiveCrossRegisterBankCopy())
19657 ++CrossRegisterBanksCopies;
19661 Loads +=
RHS.Loads;
19662 Truncates +=
RHS.Truncates;
19663 CrossRegisterBanksCopies +=
RHS.CrossRegisterBanksCopies;
19664 ZExts +=
RHS.ZExts;
19665 Shift +=
RHS.Shift;
19670 return Loads ==
RHS.Loads && Truncates ==
RHS.Truncates &&
19671 CrossRegisterBanksCopies ==
RHS.CrossRegisterBanksCopies &&
19672 ZExts ==
RHS.ZExts && Shift ==
RHS.Shift;
19680 unsigned ExpensiveOpsLHS = Loads + CrossRegisterBanksCopies;
19681 unsigned ExpensiveOpsRHS =
RHS.Loads +
RHS.CrossRegisterBanksCopies;
19684 if (!ForCodeSize && ExpensiveOpsLHS != ExpensiveOpsRHS)
19685 return ExpensiveOpsLHS < ExpensiveOpsRHS;
19686 return (Truncates + ZExts + Shift + ExpensiveOpsLHS) <
19687 (
RHS.Truncates +
RHS.ZExts +
RHS.Shift + ExpensiveOpsRHS);
19713 : Inst(Inst), Origin(Origin), Shift(Shift), DAG(DAG) {}
19718 APInt getUsedBits()
const {
19723 assert(Origin &&
"No original load to compare against.");
19725 assert(Inst &&
"This slice is not bound to an instruction");
19727 "Extracted slice is bigger than the whole type!");
19729 UsedBits.setAllBits();
19730 UsedBits = UsedBits.zext(
BitWidth);
19731 UsedBits <<= Shift;
19736 unsigned getLoadedSize()
const {
19737 unsigned SliceSize = getUsedBits().popcount();
19738 assert(!(SliceSize & 0x7) &&
"Size is not a multiple of a byte.");
19739 return SliceSize / 8;
19744 EVT getLoadedType()
const {
19745 assert(DAG &&
"Missing context");
19760 bool isLegal()
const {
19762 if (!Origin || !Inst || !DAG)
19772 EVT SliceType = getLoadedType();
19783 if (PtrType == MVT::Untyped || PtrType.
isExtended())
19796 if (TruncateType != SliceType &&
19806 uint64_t getOffsetFromBase()
const {
19807 assert(DAG &&
"Missing context.");
19809 assert(!(Shift & 0x7) &&
"Shifts not aligned on Bytes are not supported.");
19813 "The size of the original loaded type is not a multiple of a"
19818 "Invalid shift amount for given loaded size");
19831 assert(Inst && Origin &&
"Unable to replace a non-existing slice.");
19835 int64_t
Offset =
static_cast<int64_t
>(getOffsetFromBase());
19836 assert(
Offset >= 0 &&
"Offset too big to fit in int64_t!");
19846 EVT SliceType = getLoadedType();
19856 if (SliceType != FinalType)
19866 bool canMergeExpensiveCrossRegisterBankCopy()
const {
19872 assert(DAG &&
"Missing context");
19874 EVT ResVT =
User->getValueType(0);
19888 if (!
TRI ||
TRI->getCommonSubClass(ArgRC, ResRC))
19893 unsigned IsFast = 0;
19934 const LoadedSlice &Second) {
19936 "Unable to match different memory origins.");
19938 assert((UsedBits & Second.getUsedBits()) == 0 &&
19939 "Slices are not supposed to overlap.");
19940 UsedBits |= Second.getUsedBits();
19949 LoadedSlice::Cost &GlobalLSCost) {
19950 unsigned NumberOfSlices = LoadedSlices.
size();
19952 if (NumberOfSlices < 2)
19957 llvm::sort(LoadedSlices, [](
const LoadedSlice &
LHS,
const LoadedSlice &
RHS) {
19958 assert(
LHS.Origin ==
RHS.Origin &&
"Different bases not implemented.");
19959 return LHS.getOffsetFromBase() <
RHS.getOffsetFromBase();
19961 const TargetLowering &TLI = LoadedSlices[0].DAG->getTargetLoweringInfo();
19964 const LoadedSlice *
First =
nullptr;
19965 const LoadedSlice *Second =
nullptr;
19966 for (
unsigned CurrSlice = 0; CurrSlice < NumberOfSlices; ++CurrSlice,
19969 Second = &LoadedSlices[CurrSlice];
19976 EVT LoadedType =
First->getLoadedType();
19979 if (LoadedType != Second->getLoadedType())
19983 Align RequiredAlignment;
19984 if (!TLI.hasPairedLoad(LoadedType, RequiredAlignment)) {
19990 if (
First->getAlign() < RequiredAlignment)
19997 assert(GlobalLSCost.Loads > 0 &&
"We save more loads than we created!");
19998 --GlobalLSCost.Loads;
20015 const APInt &UsedBits,
bool ForCodeSize) {
20016 unsigned NumberOfSlices = LoadedSlices.
size();
20018 return NumberOfSlices > 1;
20021 if (NumberOfSlices != 2)
20029 LoadedSlice::Cost OrigCost(ForCodeSize), GlobalSlicingCost(ForCodeSize);
20031 OrigCost.Loads = 1;
20032 for (
unsigned CurrSlice = 0; CurrSlice < NumberOfSlices; ++CurrSlice) {
20033 const LoadedSlice &LS = LoadedSlices[CurrSlice];
20035 LoadedSlice::Cost SliceCost(LS, ForCodeSize);
20036 GlobalSlicingCost += SliceCost;
20040 OrigCost.addSliceGain(LS);
20045 return OrigCost > GlobalSlicingCost;
20054bool DAGCombiner::SliceUpLoad(
SDNode *
N) {
20060 !
LD->getValueType(0).isInteger())
20066 if (
LD->getValueType(0).isScalableVector())
20071 APInt UsedBits(
LD->getValueSizeInBits(0), 0);
20078 for (
SDUse &U :
LD->uses()) {
20080 if (
U.getResNo() != 0)
20084 unsigned Shift = 0;
20089 Shift =
User->getConstantOperandVal(1);
20102 unsigned Width =
User->getValueSizeInBits(0);
20107 LoadedSlice
LS(
User, LD, Shift, &DAG);
20108 APInt CurrentUsedBits =
LS.getUsedBits();
20111 if ((CurrentUsedBits & UsedBits) != 0)
20114 UsedBits |= CurrentUsedBits;
20135 for (
const LoadedSlice &LS : LoadedSlices) {
20137 CombineTo(
LS.Inst, SliceInst,
true);
20141 "It takes more than a zext to get to the loaded slice!!");
20148 AddToWorklist(Chain.
getNode());
20155static std::pair<unsigned, unsigned>
20157 std::pair<unsigned, unsigned> Result(0, 0);
20161 !isa<ConstantSDNode>(V->getOperand(1)) ||
20166 LoadSDNode *LD = cast<LoadSDNode>(V->getOperand(0));
20167 if (LD->getBasePtr() !=
Ptr)
return Result;
20170 if (V.getValueType() != MVT::i16 &&
20171 V.getValueType() != MVT::i32 &&
20172 V.getValueType() != MVT::i64)
20178 uint64_t NotMask = ~cast<ConstantSDNode>(V->getOperand(1))->getSExtValue();
20180 if (NotMaskLZ & 7)
return Result;
20182 if (NotMaskTZ & 7)
return Result;
20183 if (NotMaskLZ == 64)
return Result;
20190 if (V.getValueType() != MVT::i64 && NotMaskLZ)
20191 NotMaskLZ -= 64-V.getValueSizeInBits();
20193 unsigned MaskedBytes = (V.getValueSizeInBits()-NotMaskLZ-NotMaskTZ)/8;
20194 switch (MaskedBytes) {
20198 default:
return Result;
20203 if (NotMaskTZ && NotMaskTZ/8 % MaskedBytes)
return Result;
20212 if (!LD->isOperandOf(Chain.
getNode()))
20217 Result.first = MaskedBytes;
20218 Result.second = NotMaskTZ/8;
20229 unsigned NumBytes = MaskInfo.first;
20230 unsigned ByteShift = MaskInfo.second;
20236 ByteShift*8, (ByteShift+NumBytes)*8);
20245 bool UseTruncStore;
20246 if (DC->isTypeLegal(VT))
20247 UseTruncStore =
false;
20250 UseTruncStore =
true;
20276 StOffset = ByteShift;
20307 if (!
ST->isSimple())
20315 if (
ST->isTruncatingStore() || VT.
isVector())
20318 unsigned Opc =
Value.getOpcode();
20330 std::pair<unsigned, unsigned> MaskedLoad;
20332 if (MaskedLoad.first)
20334 Value.getOperand(1), ST,
this))
20339 if (MaskedLoad.first)
20341 Value.getOperand(0), ST,
this))
20355 if (
LD->getBasePtr() !=
Ptr ||
20356 LD->getPointerInfo().getAddrSpace() !=
20357 ST->getPointerInfo().getAddrSpace())
20366 if (Imm == 0 ||
Imm.isAllOnes())
20371 unsigned BitsPerByteMask = 7u;
20372 unsigned LSB =
Imm.countr_zero() & ~BitsPerByteMask;
20373 unsigned MSB = (
Imm.getActiveBits() - 1) | BitsPerByteMask;
20401 unsigned ShAmt = 0;
20403 for (; ShAmt + NewBW <= VTStoreSize; ShAmt += 8) {
20407 if (ShAmt + NewBW < MSB)
20412 ? VTStoreSize - NewBW - ShAmt
20414 PtrOff = PtrAdjustmentInBits / 8;
20417 unsigned IsFast = 0;
20420 LD->getAddressSpace(), NewAlign,
20421 LD->getMemOperand()->getFlags(), &IsFast) &&
20426 if (ShAmt + NewBW > VTStoreSize)
20429 APInt NewImm =
Imm.lshr(ShAmt).trunc(NewBW);
20437 LD->getPointerInfo().getWithOffset(PtrOff), NewAlign,
20438 LD->getMemOperand()->getFlags(),
LD->getAAInfo());
20443 ST->getPointerInfo().getWithOffset(PtrOff), NewAlign);
20445 AddToWorklist(NewPtr.
getNode());
20446 AddToWorklist(NewLD.
getNode());
20447 AddToWorklist(NewVal.
getNode());
20448 WorklistRemover DeadNodes(*
this);
20466 EVT VT =
LD->getMemoryVT();
20468 LD->isNonTemporal() ||
ST->isNonTemporal() ||
20469 LD->getPointerInfo().getAddrSpace() != 0 ||
20470 ST->getPointerInfo().getAddrSpace() != 0)
20480 unsigned FastLD = 0, FastST = 0;
20487 *
LD->getMemOperand(), &FastLD) ||
20489 *
ST->getMemOperand(), &FastST) ||
20490 !FastLD || !FastST)
20494 LD->getBasePtr(),
LD->getMemOperand());
20497 ST->getBasePtr(),
ST->getMemOperand());
20499 AddToWorklist(NewLD.
getNode());
20500 AddToWorklist(NewST.
getNode());
20501 WorklistRemover DeadNodes(*
this);
20523bool DAGCombiner::isMulAddWithConstProfitable(
SDNode *MulNode,
SDValue AddNode,
20535 if (
User == MulNode)
20558 if (OtherOp == MulVar)
20586 unsigned NumStores) {
20589 SDLoc StoreDL(StoreNodes[0].MemNode);
20591 for (
unsigned i = 0; i < NumStores; ++i) {
20592 Visited.
insert(StoreNodes[i].MemNode);
20596 for (
unsigned i = 0; i < NumStores; ++i) {
20597 if (Visited.
insert(StoreNodes[i].MemNode->getChain().getNode()).second)
20598 Chains.
push_back(StoreNodes[i].MemNode->getChain());
20601 assert(!Chains.
empty() &&
"Chain should have generated a chain");
20606 const Value *UnderlyingObj =
nullptr;
20607 for (
const auto &
MemOp : StoreNodes) {
20619 if (UnderlyingObj && UnderlyingObj != Obj)
20622 if (!UnderlyingObj)
20623 UnderlyingObj = Obj;
20629bool DAGCombiner::mergeStoresOfConstantsOrVecElts(
20631 bool IsConstantSrc,
bool UseVector,
bool UseTrunc) {
20636 assert((!UseTrunc || !UseVector) &&
20637 "This optimization cannot emit a vector truncating store");
20640 SDLoc DL(StoreNodes[0].MemNode);
20643 unsigned SizeInBits = NumStores * ElementSizeBits;
20646 std::optional<MachineMemOperand::Flags>
Flags;
20648 for (
unsigned I = 0;
I != NumStores; ++
I) {
20649 StoreSDNode *St = cast<StoreSDNode>(StoreNodes[
I].MemNode);
20664 unsigned Elts = NumStores * NumMemElts;
20672 if (IsConstantSrc) {
20674 for (
unsigned I = 0;
I != NumStores; ++
I) {
20675 StoreSDNode *St = cast<StoreSDNode>(StoreNodes[
I].MemNode);
20683 auto *
C = dyn_cast<ConstantSDNode>(Val);
20693 .zextOrTrunc(ElementSizeBits),
20703 DL, StoreTy, BuildVector);
20706 for (
unsigned i = 0; i < NumStores; ++i) {
20707 StoreSDNode *St = cast<StoreSDNode>(StoreNodes[i].MemNode);
20744 assert(IsConstantSrc &&
"Merged vector elements should use vector store");
20746 APInt StoreInt(SizeInBits, 0);
20751 for (
unsigned i = 0; i < NumStores; ++i) {
20752 unsigned Idx = IsLE ? (NumStores - 1 - i) : i;
20755 SDValue Val = St->getValue();
20757 StoreInt <<= ElementSizeBits;
20759 StoreInt |=
C->getAPIntValue()
20760 .zextOrTrunc(ElementSizeBits)
20761 .zextOrTrunc(SizeInBits);
20763 StoreInt |=
C->getValueAPF()
20765 .zextOrTrunc(ElementSizeBits)
20766 .zextOrTrunc(SizeInBits);
20784 SDValue NewChain = getMergeStoreChains(StoreNodes, NumStores);
20785 bool CanReusePtrInfo = hasSameUnderlyingObj(StoreNodes);
20799 FirstInChain->
getAlign(), *Flags, AAInfo);
20801 EVT LegalizedStoredValTy =
20803 unsigned LegalizedStoreSize = LegalizedStoredValTy.
getSizeInBits();
20806 DAG.
getConstant(
C->getAPIntValue().zextOrTrunc(LegalizedStoreSize),
DL,
20807 LegalizedStoredValTy);
20809 NewChain,
DL, ExtendedStoreVal, FirstInChain->
getBasePtr(),
20818 for (
unsigned i = 0; i < NumStores; ++i)
20819 CombineTo(StoreNodes[i].MemNode, NewStore);
20821 AddToWorklist(NewChain.
getNode());
20826DAGCombiner::getStoreMergeCandidates(
StoreSDNode *St,
20832 if (!
BasePtr.getBase().getNode() ||
BasePtr.getBase().isUndef())
20836 StoreSource StoreSrc = getStoreSource(Val);
20837 assert(StoreSrc != StoreSource::Unknown &&
"Expected known source for store");
20843 if (StoreSrc == StoreSource::Load) {
20844 auto *Ld = cast<LoadSDNode>(Val);
20846 LoadVT = Ld->getMemoryVT();
20848 if (MemVT != LoadVT)
20851 if (!Ld->hasNUsesOfValue(1, 0))
20855 if (!Ld->isSimple() || Ld->isIndexed())
20859 int64_t &
Offset) ->
bool {
20862 if (!
Other->isSimple() ||
Other->isIndexed())
20872 :
Other->getMemoryVT() != MemVT;
20873 switch (StoreSrc) {
20874 case StoreSource::Load: {
20878 auto *OtherLd = dyn_cast<LoadSDNode>(OtherBC);
20882 if (LoadVT != OtherLd->getMemoryVT())
20885 if (!OtherLd->hasNUsesOfValue(1, 0))
20889 if (!OtherLd->isSimple() || OtherLd->isIndexed())
20892 if (cast<LoadSDNode>(Val)->isNonTemporal() != OtherLd->isNonTemporal())
20897 if (!(LBasePtr.equalBaseIndex(LPtr, DAG)))
20901 case StoreSource::Constant:
20904 if (getStoreSource(OtherBC) != StoreSource::Constant)
20907 case StoreSource::Extract:
20909 if (
Other->isTruncatingStore())
20942 if (ChainsWithoutMergeableStores.
contains(RootNode))
20947 auto OverLimitInDependenceCheck = [&](
SDNode *StoreNode,
20948 SDNode *RootNode) ->
bool {
20949 auto RootCount = StoreRootCountMap.
find(StoreNode);
20950 return RootCount != StoreRootCountMap.
end() &&
20951 RootCount->second.first == RootNode &&
20955 auto TryToAddCandidate = [&](
SDUse &
Use) {
20959 if (
auto *OtherStore = dyn_cast<StoreSDNode>(
Use.
getUser())) {
20962 if (CandidateMatch(OtherStore,
Ptr, PtrDiff) &&
20963 !OverLimitInDependenceCheck(OtherStore, RootNode))
20964 StoreNodes.
push_back(MemOpLink(OtherStore, PtrDiff));
20968 unsigned NumNodesExplored = 0;
20969 const unsigned MaxSearchNodes = 1024;
20970 if (
auto *Ldn = dyn_cast<LoadSDNode>(RootNode)) {
20971 RootNode = Ldn->getChain().getNode();
20973 if (ChainsWithoutMergeableStores.
contains(RootNode))
20976 I != E && NumNodesExplored < MaxSearchNodes; ++
I, ++NumNodesExplored) {
20978 if (
I->getOperandNo() == 0 && isa<LoadSDNode>(
User)) {
20980 TryToAddCandidate(U2);
20983 if (
I->getOperandNo() == 0 && isa<StoreSDNode>(
User)) {
20984 TryToAddCandidate(*
I);
20989 I != E && NumNodesExplored < MaxSearchNodes; ++
I, ++NumNodesExplored)
20990 TryToAddCandidate(*
I);
20999bool DAGCombiner::checkMergeStoreCandidatesForDependencies(
21015 while (!Worklist.
empty()) {
21017 if (!Visited.
insert(
N).second)
21026 unsigned int Max = 1024 + Visited.
size();
21028 for (
unsigned i = 0; i < NumStores; ++i) {
21029 SDNode *
N = StoreNodes[i].MemNode;
21050 for (
unsigned i = 0; i < NumStores; ++i)
21056 if (Visited.
size() >= Max) {
21057 auto &RootCount = StoreRootCountMap[StoreNodes[i].MemNode];
21058 if (RootCount.first == RootNode)
21059 RootCount.second++;
21061 RootCount = {RootNode, 1};
21070 int64_t ElementSizeBytes)
const {
21073 size_t StartIdx = 0;
21074 while ((StartIdx + 1 < StoreNodes.
size()) &&
21075 StoreNodes[StartIdx].OffsetFromBase + ElementSizeBytes !=
21076 StoreNodes[StartIdx + 1].OffsetFromBase)
21080 if (StartIdx + 1 >= StoreNodes.
size())
21089 unsigned NumConsecutiveStores = 1;
21090 int64_t StartAddress = StoreNodes[0].OffsetFromBase;
21093 for (
unsigned i = 1, e = StoreNodes.
size(); i < e; ++i) {
21094 int64_t CurrAddress = StoreNodes[i].OffsetFromBase;
21095 if (CurrAddress - StartAddress != (ElementSizeBytes * i))
21097 NumConsecutiveStores = i + 1;
21099 if (NumConsecutiveStores > 1)
21100 return NumConsecutiveStores;
21108bool DAGCombiner::tryStoreMergeOfConstants(
21110 EVT MemVT,
SDNode *RootNode,
bool AllowVectors) {
21115 bool MadeChange =
false;
21118 while (NumConsecutiveStores >= 2) {
21122 unsigned LastLegalType = 1;
21123 unsigned LastLegalVectorType = 1;
21124 bool LastIntegerTrunc =
false;
21125 bool NonZero =
false;
21126 unsigned FirstZeroAfterNonZero = NumConsecutiveStores;
21127 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
21128 StoreSDNode *
ST = cast<StoreSDNode>(StoreNodes[i].MemNode);
21130 bool IsElementZero =
false;
21132 IsElementZero =
C->isZero();
21134 IsElementZero =
C->getConstantFPValue()->isNullValue();
21136 IsElementZero =
true;
21137 if (IsElementZero) {
21138 if (NonZero && FirstZeroAfterNonZero == NumConsecutiveStores)
21139 FirstZeroAfterNonZero = i;
21141 NonZero |= !IsElementZero;
21144 unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
21146 unsigned IsFast = 0;
21158 LastIntegerTrunc =
false;
21159 LastLegalType = i + 1;
21163 EVT LegalizedStoredValTy =
21171 LastIntegerTrunc =
true;
21172 LastLegalType = i + 1;
21181 unsigned Elts = (i + 1) * NumMemElts;
21188 LastLegalVectorType = i + 1;
21192 bool UseVector = (LastLegalVectorType > LastLegalType) && AllowVectors;
21193 unsigned NumElem = (UseVector) ? LastLegalVectorType : LastLegalType;
21194 bool UseTrunc = LastIntegerTrunc && !UseVector;
21206 unsigned NumSkip = 1;
21207 while ((NumSkip < NumConsecutiveStores) &&
21208 (NumSkip < FirstZeroAfterNonZero) &&
21209 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
21213 NumConsecutiveStores -= NumSkip;
21218 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
21221 NumConsecutiveStores -= NumElem;
21225 MadeChange |= mergeStoresOfConstantsOrVecElts(StoreNodes, MemVT, NumElem,
21227 UseVector, UseTrunc);
21231 NumConsecutiveStores -= NumElem;
21236bool DAGCombiner::tryStoreMergeOfExtracts(
21242 bool MadeChange =
false;
21245 while (NumConsecutiveStores >= 2) {
21249 unsigned NumStoresToMerge = 1;
21250 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
21252 unsigned Elts = (i + 1) * NumMemElts;
21254 unsigned IsFast = 0;
21265 NumStoresToMerge = i + 1;
21270 if (NumStoresToMerge < 2) {
21277 unsigned NumSkip = 1;
21278 while ((NumSkip < NumConsecutiveStores) &&
21279 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
21283 NumConsecutiveStores -= NumSkip;
21288 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumStoresToMerge,
21291 StoreNodes.
begin() + NumStoresToMerge);
21292 NumConsecutiveStores -= NumStoresToMerge;
21296 MadeChange |= mergeStoresOfConstantsOrVecElts(
21297 StoreNodes, MemVT, NumStoresToMerge,
false,
21300 StoreNodes.
erase(StoreNodes.
begin(), StoreNodes.
begin() + NumStoresToMerge);
21301 NumConsecutiveStores -= NumStoresToMerge;
21307 unsigned NumConsecutiveStores,
EVT MemVT,
21308 SDNode *RootNode,
bool AllowVectors,
21309 bool IsNonTemporalStore,
21310 bool IsNonTemporalLoad) {
21315 bool MadeChange =
false;
21324 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
21325 StoreSDNode *St = cast<StoreSDNode>(StoreNodes[i].MemNode);
21331 int64_t LdOffset = 0;
21332 if (LdBasePtr.
getBase().getNode()) {
21334 if (!LdBasePtr.equalBaseIndex(LdPtr, DAG, LdOffset))
21342 LoadNodes.
push_back(MemOpLink(Ld, LdOffset));
21345 while (NumConsecutiveStores >= 2 && LoadNodes.
size() >= 2) {
21346 Align RequiredAlignment;
21347 bool NeedRotate =
false;
21348 if (LoadNodes.
size() == 2) {
21352 StoreNodes[0].MemNode->getAlign() >= RequiredAlignment) {
21358 int64_t Offset0 = LoadNodes[0].OffsetFromBase;
21359 int64_t Offset1 = LoadNodes[1].OffsetFromBase;
21361 if (Offset0 - Offset1 == ElementSizeBytes &&
21371 LoadSDNode *FirstLoad = cast<LoadSDNode>(LoadNodes[0].MemNode);
21377 unsigned LastConsecutiveLoad = 1;
21380 unsigned LastLegalVectorType = 1;
21381 unsigned LastLegalIntegerType = 1;
21382 bool isDereferenceable =
true;
21383 bool DoIntegerTruncate =
false;
21384 int64_t StartAddress = LoadNodes[0].OffsetFromBase;
21386 for (
unsigned i = 1; i < LoadNodes.
size(); ++i) {
21388 if (LoadNodes[i].MemNode->getChain() != LoadChain)
21391 int64_t CurrAddress = LoadNodes[i].OffsetFromBase;
21392 if (CurrAddress - StartAddress != (ElementSizeBytes * i))
21394 LastConsecutiveLoad = i;
21396 if (isDereferenceable && !LoadNodes[i].MemNode->isDereferenceable())
21397 isDereferenceable =
false;
21400 unsigned Elts = (i + 1) * NumMemElts;
21407 unsigned IsFastSt = 0;
21408 unsigned IsFastLd = 0;
21422 LastLegalVectorType = i + 1;
21426 unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
21437 LastLegalIntegerType = i + 1;
21438 DoIntegerTruncate =
false;
21455 LastLegalIntegerType = i + 1;
21456 DoIntegerTruncate =
true;
21464 LastLegalVectorType > LastLegalIntegerType && AllowVectors;
21465 unsigned LastLegalType =
21466 std::max(LastLegalVectorType, LastLegalIntegerType);
21470 unsigned NumElem = std::min(NumConsecutiveStores, LastConsecutiveLoad + 1);
21471 NumElem = std::min(LastLegalType, NumElem);
21482 unsigned NumSkip = 1;
21483 while ((NumSkip < LoadNodes.
size()) &&
21484 (LoadNodes[NumSkip].MemNode->getAlign() <= FirstLoadAlign) &&
21485 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
21489 NumConsecutiveStores -= NumSkip;
21494 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
21498 NumConsecutiveStores -= NumElem;
21507 unsigned Elts = NumElem * NumMemElts;
21510 unsigned SizeInBits = NumElem * ElementSizeBytes * 8;
21514 SDLoc LoadDL(LoadNodes[0].MemNode);
21515 SDLoc StoreDL(StoreNodes[0].MemNode);
21520 SDValue NewStoreChain = getMergeStoreChains(StoreNodes, NumElem);
21521 bool CanReusePtrInfo = hasSameUnderlyingObj(StoreNodes);
21522 AddToWorklist(NewStoreChain.
getNode());
21527 if (IsNonTemporalLoad)
21539 if (UseVectorTy || !DoIntegerTruncate) {
21545 unsigned LoadWidth = ElementSizeBytes * 8 * 2;
21547 "Unexpected type for rotate-able load pair");
21554 NewStoreChain, StoreDL, StoreOp, FirstInChain->
getBasePtr(),
21557 FirstStoreAlign, StMMOFlags);
21564 FirstLoadAlign, LdMMOFlags);
21566 NewStoreChain, StoreDL, NewLoad, FirstInChain->
getBasePtr(),
21569 JointMemOpVT, FirstInChain->
getAlign(),
21574 for (
unsigned i = 0; i < NumElem; ++i) {
21575 LoadSDNode *Ld = cast<LoadSDNode>(LoadNodes[i].MemNode);
21582 for (
unsigned i = 0; i < NumElem; ++i) {
21583 SDValue Val = StoreNodes[i].MemNode->getOperand(1);
21584 CombineTo(StoreNodes[i].MemNode, NewStore);
21586 recursivelyDeleteUnusedNodes(Val.
getNode());
21592 NumConsecutiveStores -= NumElem;
21597bool DAGCombiner::mergeConsecutiveStores(
StoreSDNode *St) {
21613 if (ElementSizeBytes * 8 != (int64_t)MemVT.
getSizeInBits())
21619 const StoreSource StoreSrc = getStoreSource(StoredVal);
21620 if (StoreSrc == StoreSource::Unknown)
21625 SDNode *RootNode = getStoreMergeCandidates(St, StoreNodes);
21628 if (StoreNodes.
size() < 2)
21633 llvm::sort(StoreNodes, [](MemOpLink LHS, MemOpLink RHS) {
21634 return LHS.OffsetFromBase <
RHS.OffsetFromBase;
21638 Attribute::NoImplicitFloat);
21640 bool IsNonTemporalLoad = StoreSrc == StoreSource::Load &&
21641 cast<LoadSDNode>(StoredVal)->isNonTemporal();
21650 bool MadeChange =
false;
21651 while (StoreNodes.
size() > 1) {
21652 unsigned NumConsecutiveStores =
21653 getConsecutiveStores(StoreNodes, ElementSizeBytes);
21655 if (NumConsecutiveStores == 0)
21659 assert(NumConsecutiveStores >= 2 &&
"Expected at least 2 stores");
21660 switch (StoreSrc) {
21661 case StoreSource::Constant:
21662 MadeChange |= tryStoreMergeOfConstants(StoreNodes, NumConsecutiveStores,
21663 MemVT, RootNode, AllowVectors);
21666 case StoreSource::Extract:
21667 MadeChange |= tryStoreMergeOfExtracts(StoreNodes, NumConsecutiveStores,
21671 case StoreSource::Load:
21672 MadeChange |= tryStoreMergeOfLoads(StoreNodes, NumConsecutiveStores,
21673 MemVT, RootNode, AllowVectors,
21674 IsNonTemporalStore, IsNonTemporalLoad);
21684 ChainsWithoutMergeableStores.
insert(RootNode);
21694 if (
ST->isTruncatingStore()) {
21696 ST->getBasePtr(),
ST->getMemoryVT(),
21697 ST->getMemOperand());
21699 ReplStore = DAG.
getStore(BetterChain, SL,
ST->getValue(),
ST->getBasePtr(),
21700 ST->getMemOperand());
21705 MVT::Other,
ST->getChain(), ReplStore);
21708 AddToWorklist(Token.
getNode());
21711 return CombineTo(ST, Token,
false);
21745 if ((
isTypeLegal(MVT::i32) && !LegalOperations &&
ST->isSimple()) ||
21748 bitcastToAPInt().getZExtValue(),
SDLoc(CFP),
21755 if ((TLI.
isTypeLegal(MVT::i64) && !LegalOperations &&
21759 getZExtValue(),
SDLoc(CFP), MVT::i64);
21761 Ptr,
ST->getMemOperand());
21779 ST->getOriginalAlign(), MMOFlags, AAInfo);
21782 ST->getPointerInfo().getWithOffset(4),
21783 ST->getOriginalAlign(), MMOFlags, AAInfo);
21812 EltVT !=
Value.getOperand(0).getValueType().getVectorElementType())
21815 auto *Ld = dyn_cast<LoadSDNode>(
Value.getOperand(0));
21826 ST->getAlign(),
ST->getMemOperand()->getFlags(),
21836 if (
auto *CIdx = dyn_cast<ConstantSDNode>(
Idx)) {
21837 unsigned COffset = CIdx->getSExtValue() * EltVT.
getSizeInBits() / 8;
21839 PointerInfo =
ST->getPointerInfo().getWithOffset(COffset);
21844 return DAG.
getStore(Chain,
DL, Elt, NewPtr, PointerInfo,
ST->getAlign(),
21845 ST->getMemOperand()->getFlags());
21852 EVT MemVT =
ST->getMemoryVT();
21875 ST->isUnindexed()) {
21876 EVT SVT =
Value.getOperand(0).getValueType();
21883 if (((!LegalOperations &&
ST->isSimple()) ||
21886 DAG, *
ST->getMemOperand())) {
21888 ST->getMemOperand());
21893 if (
Value.isUndef() &&
ST->isUnindexed() && !
ST->isVolatile())
21900 if (*Alignment >
ST->getAlign() &&
21901 isAligned(*Alignment,
ST->getSrcValueOffset())) {
21904 ST->getMemoryVT(), *Alignment,
21905 ST->getMemOperand()->getFlags(),
ST->getAAInfo());
21915 if (
SDValue NewST = TransformFPLoadStorePair(
N))
21919 if (
SDValue Store = mergeTruncStores(ST))
21922 if (
ST->isUnindexed()) {
21925 if (findBetterNeighborChains(ST)) {
21930 Chain =
ST->getChain();
21934 if (
ST->isTruncatingStore() &&
ST->isUnindexed() &&
21935 Value.getValueType().isInteger() &&
21936 (!isa<ConstantSDNode>(
Value) ||
21937 !cast<ConstantSDNode>(
Value)->isOpaque())) {
21942 Value.getOperand(0).getValueType() ==
ST->getMemoryVT() &&
21945 ST->getMemOperand());
21947 APInt TruncDemandedBits =
21949 ST->getMemoryVT().getScalarSizeInBits());
21953 AddToWorklist(
Value.getNode());
21970 ST->getMemOperand());
21974 if (
auto *Cst = dyn_cast<ConstantSDNode>(
Value))
21975 if (!Cst->isOpaque()) {
21976 const APInt &CValue = Cst->getAPIntValue();
21977 APInt NewVal = CValue & TruncDemandedBits;
21978 if (NewVal != CValue) {
21982 ST->getMemoryVT(),
ST->getMemOperand());
21994 if (
auto *Ld = dyn_cast<LoadSDNode>(TruncVal)) {
21996 ST->isUnindexed() &&
ST->isSimple() &&
22007 if (
SDValue NewST = replaceStoreOfInsertLoad(ST))
22011 if (
StoreSDNode *ST1 = dyn_cast<StoreSDNode>(Chain)) {
22012 if (
ST->isUnindexed() &&
ST->isSimple() &&
22013 ST1->isUnindexed() && ST1->isSimple()) {
22015 ST1->getValue() ==
Value &&
ST->getMemoryVT() == ST1->getMemoryVT() &&
22016 ST->getAddressSpace() == ST1->getAddressSpace()) {
22023 !ST1->getBasePtr().isUndef() &&
22024 ST->getAddressSpace() == ST1->getAddressSpace()) {
22029 if (
ST->getMemoryVT().isScalableVector() ||
22030 ST1->getMemoryVT().isScalableVector()) {
22031 if (ST1->getBasePtr() ==
Ptr &&
22033 ST->getMemoryVT().getStoreSize())) {
22034 CombineTo(ST1, ST1->getChain());
22044 if (STBase.contains(DAG,
ST->getMemoryVT().getFixedSizeInBits(),
22046 ST1->getMemoryVT().getFixedSizeInBits())) {
22047 CombineTo(ST1, ST1->getChain());
22061 ST->getMemoryVT(), LegalOperations)) {
22063 Ptr,
ST->getMemoryVT(),
ST->getMemOperand());
22074 bool Changed = mergeConsecutiveStores(ST);
22075 if (!Changed)
break;
22084 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
22092 if (isa<ConstantFPSDNode>(
ST->getValue())) {
22093 if (
SDValue NewSt = replaceStoreOfFPConstant(ST))
22100 return ReduceLoadOpStoreWidth(
N);
22104 const auto *LifetimeEnd = cast<LifetimeSDNode>(
N);
22105 if (!LifetimeEnd->hasOffset())
22109 LifetimeEnd->getOffset(),
false);
22113 while (!Chains.
empty()) {
22132 if (!
ST->isSimple() ||
ST->isIndexed())
22134 const TypeSize StoreSize =
ST->getMemoryVT().getStoreSize();
22142 if (LifetimeEndBase.contains(DAG, LifetimeEnd->getSize() * 8, StoreBase,
22145 dbgs() <<
"\nwithin LIFETIME_END of : ";
22146 LifetimeEndBase.dump();
dbgs() <<
"\n");
22147 CombineTo(ST,
ST->getChain());
22190 if (!
ST->isSimple())
22223 !
Lo.getOperand(0).getValueType().isScalarInteger() ||
22224 Lo.getOperand(0).getValueSizeInBits() > HalfValBitSize ||
22226 !
Hi.getOperand(0).getValueType().isScalarInteger() ||
22227 Hi.getOperand(0).getValueSizeInBits() > HalfValBitSize)
22233 ?
Lo.getOperand(0).getValueType()
22234 :
Lo.getValueType();
22236 ?
Hi.getOperand(0).getValueType()
22237 :
Hi.getValueType();
22254 ST->getOriginalAlign(), MMOFlags, AAInfo);
22259 St0,
DL,
Hi,
Ptr,
ST->getPointerInfo().getWithOffset(HalfValBitSize / 8),
22260 ST->getOriginalAlign(), MMOFlags, AAInfo);
22271 unsigned InsIndex) {
22280 int ElementOffset = -1;
22289 while (!ArgWorkList.
empty()) {
22292 std::tie(ArgOffset, ArgVal) = ArgWorkList.
pop_back_val();
22294 if (ArgVal == InsertVal0) {
22295 ElementOffset = ArgOffset;
22301 int CurrentArgOffset =
22305 CurrentArgOffset -= Step;
22311 assert(CurrentArgOffset == ArgOffset);
22317 if (ElementOffset == -1) {
22318 if (!
Y.isUndef() || InsertVal0.
getValueType() !=
Y.getValueType())
22320 ElementOffset = Mask.size();
22324 NewMask.
assign(Mask.begin(), Mask.end());
22326 assert(NewMask[InsIndex] < (
int)(2 * Mask.size()) && NewMask[InsIndex] >= 0 &&
22327 "NewMask[InsIndex] is out of bound");
22336SDValue DAGCombiner::mergeInsertEltWithShuffle(
SDNode *
N,
unsigned InsIndex) {
22338 "Expected extract_vector_elt");
22339 SDValue InsertVal =
N->getOperand(1);
22342 auto *SVN = dyn_cast<ShuffleVectorSDNode>(Vec);
22355 return LegalShuffle;
22366SDValue DAGCombiner::combineInsertEltToShuffle(
SDNode *
N,
unsigned InsIndex) {
22368 "Expected extract_vector_elt");
22369 SDValue InsertVal =
N->getOperand(1);
22376 SDValue DestVec =
N->getOperand(0);
22382 if (NumSrcElts == 1)
22385 unsigned NumMaskVals = ExtendRatio * NumSrcElts;
22393 for (
unsigned i = 0; i != NumMaskVals; ++i) {
22394 if (i / NumSrcElts == InsIndex)
22395 Mask[i] = (i % NumSrcElts) + NumMaskVals;
22410 ConcatOps[0] = SubVec;
22416 AddToWorklist(PaddedSubV.
getNode());
22417 AddToWorklist(DestVecBC.
getNode());
22418 AddToWorklist(Shuf.
getNode());
22425SDValue DAGCombiner::combineInsertEltToLoad(
SDNode *
N,
unsigned InsIndex) {
22426 EVT VT =
N->getValueType(0);
22435 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(0));
22438 return InsIndex == P.index() || P.value() < 0 ||
22439 (InsIndex == 0 && P.value() == (int)P.index() - 1) ||
22440 (InsIndex == VT.getVectorNumElements() - 1 &&
22441 P.value() == (int)P.index() + 1);
22447 unsigned Extend = 0;
22451 Extend =
Scalar.getOpcode();
22455 auto *ScalarLoad = dyn_cast<LoadSDNode>(Scalar);
22465 auto *
VecLoad = dyn_cast<LoadSDNode>(Vec);
22469 int EltSize = ScalarLoad->getValueType(0).getScalarSizeInBits();
22470 if (EltSize == 0 || EltSize % 8 != 0 || !ScalarLoad->isSimple() ||
22473 ScalarLoad->getAddressSpace() !=
VecLoad->getAddressSpace())
22478 if (InsIndex == 0) {
22489 unsigned IsFast = 0;
22493 NewAlign,
VecLoad->getMemOperand()->getFlags(),
22505 InsIndex == 0 ? ScalarLoad->getPointerInfo()
22506 :
VecLoad->getPointerInfo().getWithOffset(EltSize / 8);
22509 ScalarLoad->getChain(),
Ptr, PtrInfo, NewAlign);
22522 auto *IndexC = dyn_cast<ConstantSDNode>(EltNo);
22549 unsigned Elt = IndexC->getZExtValue();
22552 if (NumElts == 1) {
22568 && isa<ConstantSDNode>(InVec.
getOperand(2))) {
22570 if (Elt < OtherElt) {
22574 AddToWorklist(NewOp.
getNode());
22580 if (
SDValue Shuf = mergeInsertEltWithShuffle(
N, Elt))
22583 if (
SDValue Shuf = combineInsertEltToShuffle(
N, Elt))
22586 if (
SDValue Shuf = combineInsertEltToLoad(
N, Elt))
22602 EVT EltVT = Elt.getValueType();
22603 MaxEltVT = MaxEltVT.
bitsGE(EltVT) ? MaxEltVT : EltVT;
22611 assert(Ops.
size() == NumElts &&
"Unexpected vector size");
22625 for (
SDValue CurVec = InVec; CurVec;) {
22627 if (CurVec.isUndef())
22628 return CanonicalizeBuildVector(Ops);
22632 for (
unsigned I = 0;
I != NumElts; ++
I)
22633 AddBuildVectorOp(Ops, CurVec.getOperand(
I),
I);
22634 return CanonicalizeBuildVector(Ops);
22639 AddBuildVectorOp(Ops, CurVec.getOperand(0), 0);
22640 return CanonicalizeBuildVector(Ops);
22645 if (
auto *CurIdx = dyn_cast<ConstantSDNode>(CurVec.getOperand(2)))
22646 if (CurIdx->getAPIntValue().ult(NumElts)) {
22647 unsigned Idx = CurIdx->getZExtValue();
22648 AddBuildVectorOp(Ops, CurVec.getOperand(1),
Idx);
22652 return CanonicalizeBuildVector(Ops);
22654 CurVec = CurVec->getOperand(0);
22662 auto *SVN = cast<ShuffleVectorSDNode>(CurVec);
22666 bool Merged =
true;
22675 Mask = std::move(NewMask);
22692 for (
unsigned I = 0;
I != NumElts; ++
I)
22705 for (
unsigned I = 0;
I != NumElts; ++
I)
22712 for (
unsigned I = 0;
I != NumElts; ++
I)
22716 return CanonicalizeBuildVector(Ops);
22723SDValue DAGCombiner::scalarizeExtractedVectorLoad(
SDNode *EVE,
EVT InVecVT,
22746 if (
auto *ConstEltNo = dyn_cast<ConstantSDNode>(EltNo)) {
22747 int Elt = ConstEltNo->getZExtValue();
22758 unsigned IsFast = 0;
22772 if (ResultVT.
bitsGT(VecEltVT)) {
22779 NewPtr, MPI, VecEltVT, Alignment,
22789 if (ResultVT.
bitsLT(VecEltVT))
22801 const SDLoc &
DL,
bool LegalTypes) {
22805 auto *IndexC = dyn_cast<ConstantSDNode>(Index);
22839 DL, ResVT, Op0, Op1, cast<CondCodeSDNode>(Vec->
getOperand(2))->get());
22843 if (ResVT != MVT::i1 &&
22856 return DAG.
getNode(Opc,
DL, ResVT, Op0, Op1);
22868bool DAGCombiner::refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
22885 auto *IndexC = dyn_cast<ConstantSDNode>(
N->getOperand(1));
22890 "Original ISD::EXTRACT_VECTOR_ELT is undefinend?");
22894 EVT ScalarVT =
N->getValueType(0);
22910 Entry(Entry &&) =
default;
22911 Entry(
SDNode *Producer_,
unsigned BitPos_,
int NumBits_)
22912 :
Producer(Producer_), BitPos(BitPos_), NumBits(NumBits_) {}
22915 Entry(
const Entry &) =
delete;
22916 Entry &operator=(
const Entry &) =
delete;
22917 Entry &operator=(Entry &&) =
delete;
22923 Worklist.
emplace_back(
N, VecEltBitWidth * IndexC->getZExtValue(),
22926 while (!Worklist.
empty()) {
22933 bool ProducerIsLeaf =
false;
22936 switch (
User->getOpcode()) {
22944 User->getValueSizeInBits(0));
22950 if (
auto *ShAmtC = dyn_cast<ConstantSDNode>(
User->
getOperand(1));
22954 unsigned ShAmt = ShAmtC->getZExtValue();
22962 ProducerIsLeaf =
true;
22970 if (ProducerIsLeaf)
22974 unsigned NewVecEltBitWidth = Leafs.
front().NumBits;
22977 if (NewVecEltBitWidth == VecEltBitWidth)
22987 if (!
all_of(Leafs, [NewVecEltBitWidth](
const Entry &E) {
22988 return (
unsigned)E.NumBits == NewVecEltBitWidth &&
22989 E.Producer->getValueSizeInBits(0) == NewVecEltBitWidth &&
22990 E.BitPos % NewVecEltBitWidth == 0;
23002 if (LegalOperations &&
23008 for (
const Entry &E : Leafs) {
23010 unsigned NewIndex = E.BitPos / NewVecEltBitWidth;
23012 "Creating out-of-bounds ISD::EXTRACT_VECTOR_ELT?");
23015 CombineTo(E.Producer, V);
23024 EVT ScalarVT =
N->getValueType(0);
23037 AddUsersToWorklist(VecOp.
getNode());
23061 auto *IndexC = dyn_cast<ConstantSDNode>(Index);
23072 "BUILD_VECTOR used for scalable vectors");
23073 unsigned IndexVal =
23081 if (ScalarVT == InEltVT)
23121 unsigned ExtractIndex = IndexC->getZExtValue();
23123 unsigned BCTruncElt = IsLE ? 0 : NumElts - 1;
23136 EVT XVT =
X.getValueType();
23138 "Extract element and scalar to vector can't change element type "
23139 "from FP to integer.");
23140 unsigned XBitWidth =
X.getValueSizeInBits();
23141 unsigned Scale = XBitWidth / VecEltBitWidth;
23142 BCTruncElt = IsLE ? 0 : Scale - 1;
23147 if (ExtractIndex < Scale && XBitWidth > VecEltBitWidth) {
23148 assert(XBitWidth % VecEltBitWidth == 0 &&
23149 "Scalar bitwidth must be a multiple of vector element bitwidth");
23151 if (ExtractIndex != BCTruncElt) {
23152 unsigned ShiftIndex =
23153 IsLE ? ExtractIndex : (Scale - 1) - ExtractIndex;
23171 auto *Shuf = cast<ShuffleVectorSDNode>(VecOp);
23173 int OrigElt = Shuf->getMaskElt(IndexC->getZExtValue());
23181 if (OrigElt < (
int)NumElts) {
23185 OrigElt -= NumElts;
23201 if (!LegalOperations ||
23213 return Use->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
23214 Use->getOperand(0) == VecOp &&
23215 isa<ConstantSDNode>(Use->getOperand(1));
23220 if (CstElt->getAPIntValue().ult(NumElts))
23221 DemandedElts.
setBit(CstElt->getZExtValue());
23240 if (refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
N))
23246 bool BCNumEltsChanged =
false;
23261 BCNumEltsChanged =
true;
23267 if (!LegalOperations && !IndexC && VecOp.
hasOneUse() &&
23270 auto *
VecLoad = dyn_cast<LoadSDNode>(VecOp);
23271 if (VecLoad &&
VecLoad->isSimple())
23272 return scalarizeExtractedVectorLoad(
N, VecVT, Index, VecLoad);
23277 if (!LegalOperations || !IndexC)
23283 int Elt = IndexC->getZExtValue();
23286 LN0 = cast<LoadSDNode>(VecOp);
23294 LN0 = cast<LoadSDNode>(VecOp.
getOperand(0));
23296 if (
auto *Shuf = dyn_cast<ShuffleVectorSDNode>(VecOp)) {
23307 if (BCNumEltsChanged)
23311 int Idx = (Elt > (int)NumElts) ? -1 : Shuf->getMaskElt(Elt);
23322 LN0 = cast<LoadSDNode>(VecOp);
23323 Elt = (
Idx < (int)NumElts) ?
Idx :
Idx - (int)NumElts;
23342 Index.getValueType());
23360 return scalarizeExtractedVectorLoad(
N, VecVT, Index, LN0);
23374 unsigned NumInScalars =
N->getNumOperands();
23376 EVT VT =
N->getValueType(0);
23383 EVT SourceType = MVT::Other;
23384 bool AllAnyExt =
true;
23386 for (
unsigned i = 0; i != NumInScalars; ++i) {
23389 if (
In.isUndef())
continue;
23395 if (!ZeroExt && !AnyExt) {
23396 SourceType = MVT::Other;
23401 EVT InTy =
In.getOperand(0).getValueType();
23404 if (SourceType == MVT::Other)
23407 else if (InTy != SourceType) {
23409 SourceType = MVT::Other;
23414 AllAnyExt &= AnyExt;
23422 SourceType != MVT::Other &&
23423 llvm::has_single_bit<uint32_t>(OutScalarTy.
getSizeInBits()) &&
23424 llvm::has_single_bit<uint32_t>(SourceType.
getSizeInBits());
23438 assert(ElemRatio > 1 &&
"Invalid element size ratio");
23446 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
23450 Cast.
isUndef()) &&
"Invalid cast opcode");
23456 unsigned Index = isLE ? (i * ElemRatio) :
23457 (i * ElemRatio + (ElemRatio - 1));
23459 assert(Index < Ops.size() &&
"Invalid index");
23466 "Invalid vector size");
23489 EVT VT =
N->getValueType(0);
23508 unsigned NumInScalars =
N->getNumOperands();
23511 auto PeekThroughBitcast = [](
SDValue Op) {
23513 return Op.getOperand(0);
23519 for (
unsigned i = 0; i != NumInScalars; ++i) {
23520 SDValue In = PeekThroughBitcast(
N->getOperand(i));
23522 if (
In.isUndef())
continue;
23527 In = PeekThroughBitcast(
In.getOperand(0));
23538 SDValue part = PeekThroughBitcast(
In.getOperand(0));
23542 }
else if (Src != part) {
23547 SDValue ShiftAmtVal =
In.getOperand(1);
23548 if (!isa<ConstantSDNode>(ShiftAmtVal))
23551 uint64_t ShiftAmt =
In.getConstantOperandVal(1);
23554 if (ShiftAmt != i * ScalarTypeBitsize)
23560 if (!Src || Src.getValueType().getSizeInBits() != VT.
getSizeInBits())
23569 unsigned LeftIdx,
bool DidSplitVec) {
23572 EVT VT =
N->getValueType(0);
23577 unsigned ShuffleNumElems = NumElems;
23587 assert(InVT2Size <= InVT1Size &&
23588 "Inputs must be sorted to be in non-increasing vector size order.");
23592 if (InVT1 != VT || InVT2 != VT) {
23593 if ((VTSize % InVT1Size == 0) && InVT1 == InVT2) {
23596 unsigned NumConcats = VTSize / InVT1Size;
23597 assert(NumConcats >= 2 &&
"Concat needs at least two inputs!");
23599 ConcatOps[0] = VecIn1;
23600 ConcatOps[1] = VecIn2 ? VecIn2 : DAG.
getUNDEF(InVT1);
23603 }
else if (InVT1Size == VTSize * 2) {
23615 Vec2Offset = NumElems;
23617 assert(InVT2Size <= InVT1Size &&
23618 "Second input is not going to be larger than the first one.");
23624 if (LegalOperations &&
23631 if (InVT1 != InVT2) {
23635 DAG.
getUNDEF(InVT1), VecIn2, ZeroIdx);
23637 ShuffleNumElems = NumElems * 2;
23639 }
else if (InVT2Size * 2 == VTSize && InVT1Size == VTSize) {
23641 ConcatOps[0] = VecIn2;
23643 }
else if (InVT1Size / VTSize > 1 && InVT1Size % VTSize == 0) {
23651 assert(InVT2Size <= InVT1Size &&
23652 "Second input is not going to be larger than the first one.");
23661 if (InVT1 != InVT2) {
23663 DAG.
getUNDEF(InVT1), VecIn2, ZeroIdx);
23665 ShuffleNumElems = InVT1Size / VTSize * NumElems;
23681 for (
unsigned i = 0; i != NumElems; ++i) {
23682 if (VectorMask[i] <= 0)
23685 unsigned ExtIndex =
N->getOperand(i).getConstantOperandVal(1);
23686 if (VectorMask[i] == (
int)LeftIdx) {
23687 Mask[i] = ExtIndex;
23688 }
else if (VectorMask[i] == (
int)LeftIdx + 1) {
23689 Mask[i] = Vec2Offset + ExtIndex;
23702 if (ShuffleNumElems > NumElems)
23715 for (
int i = 0; i != NumBVOps; ++i) {
23747 if (DestSize % SrcSize != 0 ||
23753 int ZextRatio = DestSize / SrcSize;
23754 int NumMaskElts = NumBVOps * ZextRatio;
23756 for (
int i = 0; i != NumMaskElts; ++i) {
23757 if (i / ZextRatio == ZextElt) {
23778 ZeroVec, ShufMask, DAG);
23785template <
typename R,
typename T>
23789 return static_cast<decltype(std::distance(
Range.begin(),
I))
>(-1);
23790 return std::distance(
Range.begin(),
I);
23798 EVT VT =
N->getValueType(0);
23811 bool UsesZeroVector =
false;
23812 unsigned NumElems =
N->getNumOperands();
23826 unsigned OneConstExtractIndex = ~0
u;
23829 unsigned NumExtracts = 0;
23831 for (
unsigned i = 0; i != NumElems; ++i) {
23841 UsesZeroVector =
true;
23851 SDValue ExtractedFromVec =
Op.getOperand(0);
23854 auto *ExtractIdx = dyn_cast<ConstantSDNode>(
Op.getOperand(1));
23858 if (ExtractIdx->getAsAPIntVal().uge(
23867 OneConstExtractIndex = ExtractIdx->getZExtValue();
23879 VectorMask[i] =
Idx;
23883 if (VecIn.
size() < 2)
23890 bool DidSplitVec =
false;
23891 if (VecIn.
size() == 2) {
23900 if (NumExtracts == 1 &&
23906 unsigned MaxIndex = 0;
23907 unsigned NearestPow2 = 0;
23912 for (
unsigned i = 0; i < NumElems; i++) {
23913 if (VectorMask[i] <= 0)
23915 unsigned Index =
N->getOperand(i).getConstantOperandVal(1);
23916 IndexVec[i] =
Index;
23917 MaxIndex = std::max(MaxIndex, Index);
23921 if (InVT.
isSimple() && NearestPow2 > 2 && MaxIndex < NearestPow2 &&
23922 NumElems * 2 < NearestPow2) {
23923 unsigned SplitSize = NearestPow2 / 2;
23936 DidSplitVec =
true;
23938 for (
unsigned i = 0; i < NumElems; i++) {
23939 if (VectorMask[i] <= 0)
23941 VectorMask[i] = (IndexVec[i] < SplitSize) ? 1 : 2;
23954 b.getValueType().getVectorNumElements();
23959 for (
int &SourceVectorIndex : VectorMask) {
23960 if (SourceVectorIndex <= 0)
23964 VecIn[SourceVectorIndex] == SortedVecIn[
Idx] &&
"Remapping failure");
23965 SourceVectorIndex =
Idx;
23968 VecIn = std::move(SortedVecIn);
23986 for (
unsigned In = 0, Len = (VecIn.
size() / 2); In < Len; ++In) {
23987 unsigned LeftIdx = 2 *
In + 1;
23988 SDValue VecLeft = VecIn[LeftIdx];
23990 (LeftIdx + 1) < VecIn.
size() ? VecIn[LeftIdx + 1] :
SDValue();
23992 if (
SDValue Shuffle = createBuildVecShuffle(
DL,
N, VectorMask, VecLeft,
23993 VecRight, LeftIdx, DidSplitVec))
24001 if (UsesZeroVector)
24006 if (Shuffles.
size() == 1)
24007 return Shuffles[0];
24010 for (
int &Vec : VectorMask)
24012 Vec = Shuffles.
size() - 1;
24014 Vec = (Vec - 1) / 2;
24028 if (Shuffles.
size() % 2)
24031 for (
unsigned CurSize = Shuffles.
size(); CurSize > 1; CurSize /= 2) {
24033 Shuffles[CurSize] = DAG.
getUNDEF(VT);
24036 for (
unsigned In = 0, Len = CurSize / 2;
In <
Len; ++
In) {
24043 L.use_empty() &&
L.getOperand(1).isUndef() &&
24044 L.getOperand(0).getValueType() ==
L.getValueType();
24045 if (IsLeftShuffle) {
24046 LMask = cast<ShuffleVectorSDNode>(
L.getNode())->getMask();
24047 L =
L.getOperand(0);
24052 R.use_empty() &&
R.getOperand(1).isUndef() &&
24053 R.getOperand(0).getValueType() ==
R.getValueType();
24054 if (IsRightShuffle) {
24055 RMask = cast<ShuffleVectorSDNode>(
R.getNode())->getMask();
24056 R =
R.getOperand(0);
24058 for (
unsigned I = 0;
I != NumElems; ++
I) {
24059 if (VectorMask[
I] ==
Left) {
24063 VectorMask[
I] =
In;
24064 }
else if (VectorMask[
I] ==
Right) {
24066 if (IsRightShuffle)
24067 Mask[
I] = RMask[
I] + NumElems;
24068 VectorMask[
I] =
In;
24075 return Shuffles[0];
24083 if (LegalOperations)
24086 EVT VT =
N->getValueType(0);
24088 bool FoundZeroExtend =
false;
24090 auto checkElem = [&](
SDValue Op) -> int64_t {
24091 unsigned Opc =
Op.getOpcode();
24096 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op.getOperand(0).getOperand(1)))
24097 return C->getZExtValue();
24105 int64_t
Offset = checkElem(Op0);
24109 unsigned NumElems =
N->getNumOperands();
24111 EVT InSVT =
In.getValueType().getScalarType();
24119 for (
unsigned i = 1; i != NumElems; ++i) {
24120 if ((
Offset + i) != checkElem(
N->getOperand(i)))
24138SDValue DAGCombiner::convertBuildVecZextToBuildVecWithZeros(
SDNode *
N) {
24147 EVT VT =
N->getValueType(0);
24148 EVT OpVT =
N->getOperand(0).getValueType();
24162 unsigned ActiveBits = 0;
24167 if (
auto *Cst = dyn_cast<ConstantSDNode>(
Op)) {
24168 unsigned OpActiveBits =
24169 Cst->getAPIntValue().trunc(EltBitwidth).getActiveBits();
24170 if (OpActiveBits == 0) {
24171 KnownZeroOps.setBit(
I.index());
24179 if (
I.index() != 0)
24185 unsigned CurrActiveBits =
24186 Op.getOperand(0).getValueSizeInBits().getFixedValue();
24187 assert(!ActiveBits &&
"Already encountered non-constant-zero operand?");
24188 ActiveBits = CurrActiveBits;
24190 if (2 * ActiveBits > EltBitwidth)
24195 if (ActiveBits == 0)
24200 EVT NewScalarIntVT, NewIntVT;
24201 std::optional<unsigned> Factor;
24206 assert(2 * ActiveBits <= EltBitwidth &&
24207 "We know that half or less bits of the element are active.");
24208 for (
unsigned Scale = EltBitwidth / ActiveBits; Scale >= 2; --Scale) {
24209 if (EltBitwidth % Scale != 0)
24211 unsigned ChunkBitwidth = EltBitwidth / Scale;
24212 assert(ChunkBitwidth >= ActiveBits &&
"As per starting point.");
24215 Scale *
N->getNumOperands());
24217 (LegalOperations &&
24235 assert(!
Op.isUndef() &&
"FIXME: after allowing UNDEF's, handle them here.");
24236 unsigned SrcOpIdx =
I.index();
24237 if (KnownZeroOps[SrcOpIdx]) {
24238 NewOps.
append(*Factor, ZeroOp);
24244 NewOps.
append(*Factor - 1, ZeroOp);
24253 EVT VT =
N->getValueType(0);
24267 if (!LegalOperations) {
24268 SDValue Splat = cast<BuildVectorSDNode>(
N)->getSplatValue();
24289 if (!LegalTypes && (
N->getNumOperands() > 1)) {
24294 if (
auto CNode = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
24299 int Offset = checkElem(Op0);
24300 for (
unsigned i = 0; i <
N->getNumOperands(); ++i) {
24301 if (
Offset + i != checkElem(
N->getOperand(i))) {
24311 ((
Offset %
N->getValueType(0).getVectorNumElements()) ==
24317 if (
SDValue V = convertBuildVecZextToZext(
N))
24320 if (
SDValue V = convertBuildVecZextToBuildVecWithZeros(
N))
24323 if (
SDValue V = reduceBuildVecExtToExtBuildVec(
N))
24326 if (
SDValue V = reduceBuildVecTruncToBitCast(
N))
24329 if (
SDValue V = reduceBuildVecToShuffle(
N))
24336 assert(!
V.isUndef() &&
"Splat of undef should have been handled earlier");
24345 EVT OpVT =
N->getOperand(0).getValueType();
24352 EVT VT =
N->getValueType(0);
24361 !
Op.getOperand(0).getValueType().isVector())
24370 EVT LastOpVT = Ops.
back().getValueType();
24372 AnyFPVT = LastOpVT;
24380 if (AnyFPVT !=
EVT()) {
24383 if (
Op.getValueType() == SVT)
24402 EVT VT =
N->getValueType(0);
24412 if (!FirstConcat) {
24413 SubVT =
Op.getOperand(0).getValueType();
24419 if (SubVT !=
Op.getOperand(0).getValueType())
24422 assert(FirstConcat &&
"Concat of all-undefs found");
24426 if (
Op.isUndef()) {
24430 ConcatOps.
append(
Op->op_begin(),
Op->op_end());
24440 EVT VT =
N->getValueType(0);
24441 EVT OpVT =
N->getOperand(0).getValueType();
24457 if (
Op.isUndef()) {
24458 Mask.append((
unsigned)NumOpElts, -1);
24467 int ExtIdx =
Op.getConstantOperandVal(1);
24476 Mask.append((
unsigned)NumOpElts, -1);
24487 if (0 == (NumExtElts % NumElts))
24488 ExtIdx /= (NumExtElts / NumElts);
24489 else if (0 == (NumElts % NumExtElts))
24490 ExtIdx *= (NumElts / NumExtElts);
24495 if (SV0.
isUndef() || SV0 == ExtVec) {
24497 for (
int i = 0; i != NumOpElts; ++i)
24498 Mask.push_back(i + ExtIdx);
24499 }
else if (SV1.
isUndef() || SV1 == ExtVec) {
24501 for (
int i = 0; i != NumOpElts; ++i)
24502 Mask.push_back(i + ExtIdx + NumElts);
24514 unsigned CastOpcode =
N->getOperand(0).getOpcode();
24515 switch (CastOpcode) {
24531 EVT SrcVT =
N->getOperand(0).getOperand(0).getValueType();
24539 if (
Op.getOpcode() != CastOpcode || !
Op.hasOneUse() ||
24540 Op.getOperand(0).getValueType() != SrcVT)
24548 EVT VT =
N->getValueType(0);
24553 switch (CastOpcode) {
24573 return DAG.
getNode(CastOpcode,
DL, VT, NewConcat);
24581 bool LegalOperations) {
24582 EVT VT =
N->getValueType(0);
24583 EVT OpVT =
N->getOperand(0).getValueType();
24588 if (
N->getNumOperands() != 2)
24593 (LegalOperations &&
24604 if (
auto *CurSVN = dyn_cast<ShuffleVectorSDNode>(
Op);
24605 CurSVN && CurSVN->getOperand(1).
isUndef() &&
N->isOnlyUserOf(CurSVN) &&
24608 return !Op.isUndef() &&
24609 (Op.getNode() == CurSVN || is_contained(CurSVN->ops(), Op));
24632 std::iota(FirstShufOpIdentityMask.
begin(), FirstShufOpIdentityMask.
end(), 0);
24633 std::iota(SecondShufOpIdentityMask.
begin(), SecondShufOpIdentityMask.
end(),
24640 assert(!
Op.isUndef() &&
"Not expecting to concatenate UNDEF.");
24641 if (
Op.getNode() == SVN) {
24662 std::array<SDValue, 2> ShufOps;
24663 for (
auto I :
zip(SVN->
ops(), ShufOps)) {
24665 SDValue &NewShufOp = std::get<1>(
I);
24671 ShufOpParts[0] = ShufOp;
24681 if (
N->getNumOperands() == 1)
24682 return N->getOperand(0);
24685 EVT VT =
N->getValueType(0);
24691 [](
const SDValue &
Op) { return Op.isUndef(); })) {
24693 assert(
In.getValueType().isVector() &&
"Must concat vectors");
24703 !(LegalDAG &&
In.getValueType().isScalableVector())) {
24704 unsigned NumOps =
N->getNumOperands() *
In.getNumOperands();
24706 Ops.resize(NumOps, DAG.
getUNDEF(Ops[0].getValueType()));
24716 EVT SVT =
Scalar.getValueType().getVectorElementType();
24717 if (SVT ==
Scalar.getOperand(0).getValueType())
24722 if (!
Scalar.getValueType().isVector() &&
In.hasOneUse()) {
24741 if (VNTNumElms < 2)
24757 auto IsBuildVectorOrUndef = [](
const SDValue &
Op) {
24768 bool FoundMinVT =
false;
24771 EVT OpSVT =
Op.getOperand(0).getValueType();
24772 MinVT = (!FoundMinVT || OpSVT.
bitsLE(MinVT)) ? OpSVT : MinVT;
24775 assert(FoundMinVT &&
"Concat vector type mismatch");
24779 EVT OpVT =
Op.getValueType();
24788 Opnds.
append(
Op->op_begin(),
Op->op_begin() + NumElts);
24790 for (
unsigned i = 0; i != NumElts; ++i)
24798 "Concat vector type mismatch");
24821 N, DAG, TLI, LegalTypes, LegalOperations))
24831 unsigned PartNumElem =
24832 N->getOperand(0).getValueType().getVectorMinNumElements();
24834 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
24845 if (SingleSource.
getNode()) {
24846 if (
Op.getOperand(0) != SingleSource)
24849 SingleSource =
Op.getOperand(0);
24859 unsigned IdentityIndex = i * PartNumElem;
24860 if (
Op.getConstantOperandAPInt(1) != IdentityIndex)
24865 return SingleSource;
24874 V.getOperand(1).getValueType() == SubVT && V.getOperand(2) == Index) {
24875 return V.getOperand(1);
24877 auto *IndexC = dyn_cast<ConstantSDNode>(Index);
24879 V.getOperand(0).getValueType() == SubVT &&
24882 return V.getOperand(SubIdx);
24889 bool LegalOperations) {
24892 unsigned BinOpcode = BinOp.
getOpcode();
24898 if (VecVT != Bop0.
getValueType() || VecVT != Bop1.getValueType())
24912 if (!Sub0 || !Sub1)
24918 return DAG.
getNode(BinOpcode,
SDLoc(Extract), SubVT, Sub0, Sub1,
24925 bool LegalOperations) {
24933 auto *ExtractIndexC = dyn_cast<ConstantSDNode>(Extract->
getOperand(1));
24934 if (!ExtractIndexC)
24950 if (
C &&
C->getValueAPF().isNegZero())
24963 unsigned ExtractIndex = ExtractIndexC->getZExtValue();
24965 "Extract index is not a multiple of the vector length.");
24970 if (WideWidth % NarrowWidth != 0)
24975 unsigned NarrowingRatio = WideWidth / NarrowWidth;
24977 if (WideNumElts % NarrowingRatio != 0)
24982 WideNumElts / NarrowingRatio);
25009 if (NarrowingRatio != 2)
25024 return V.getOperand(ConcatOpNum);
25030 if (SubVecL || SubVecR) {
25061 auto *Ld = dyn_cast<LoadSDNode>(Extract->
getOperand(0));
25081 assert(Index % NumElts == 0 &&
"The extract subvector index is not a "
25082 "multiple of the result's element count");
25101 if (
Offset.isScalable()) {
25124 bool LegalOperations) {
25126 "Must only be called on EXTRACT_SUBVECTOR's");
25131 EVT NarrowVT =
N->getValueType(0);
25137 auto *WideShuffleVector = dyn_cast<ShuffleVectorSDNode>(N0);
25138 if (!WideShuffleVector)
25142 if (!WideShuffleVector->hasOneUse())
25146 if (LegalOperations &&
25150 uint64_t FirstExtractedEltIdx =
N->getConstantOperandVal(1);
25152 assert((FirstExtractedEltIdx % NumEltsExtracted) == 0 &&
25153 "Extract index is not a multiple of the output vector length.");
25158 NewMask.
reserve(NumEltsExtracted);
25160 DemandedSubvectors;
25163 for (
int M : WideShuffleVector->getMask().slice(FirstExtractedEltIdx,
25164 NumEltsExtracted)) {
25165 assert((M >= -1) && (M < (2 * WideNumElts)) &&
25166 "Out-of-bounds shuffle mask?");
25175 int WideShufOpIdx = M / WideNumElts;
25177 int OpEltIdx = M % WideNumElts;
25179 assert((OpEltIdx + WideShufOpIdx * WideNumElts) == M &&
25180 "Shuffle mask vector decomposition failure.");
25183 int OpSubvecIdx = OpEltIdx / NumEltsExtracted;
25185 int OpEltIdxInSubvec = OpEltIdx % NumEltsExtracted;
25187 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted) == OpEltIdx &&
25188 "Shuffle mask subvector decomposition failure.");
25190 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted +
25191 WideShufOpIdx * WideNumElts) == M &&
25192 "Shuffle mask full decomposition failure.");
25194 SDValue Op = WideShuffleVector->getOperand(WideShufOpIdx);
25196 if (
Op.isUndef()) {
25202 const std::pair<SDValue, int> DemandedSubvector =
25203 std::make_pair(
Op, OpSubvecIdx);
25205 if (DemandedSubvectors.insert(DemandedSubvector)) {
25206 if (DemandedSubvectors.size() > 2)
25209 int Index = NumEltsExtracted * OpSubvecIdx;
25217 getFirstIndexOf(DemandedSubvectors.getArrayRef(), DemandedSubvector);
25218 assert((NewOpIdx == 0 || NewOpIdx == 1) &&
"Unexpected operand index.");
25220 int AdjM = OpEltIdxInSubvec + NewOpIdx * NumEltsExtracted;
25223 assert(NewMask.
size() == (
unsigned)NumEltsExtracted &&
"Produced bad mask.");
25224 assert(DemandedSubvectors.size() <= 2 &&
25225 "Should have ended up demanding at most two subvectors.");
25228 if (DemandedSubvectors.empty())
25234 any_of(NewMask, [](
int M) {
return M < 0; }))
25235 for (
auto &DemandedSubvector : DemandedSubvectors)
25236 if (DemandedSubvector.second != 0)
25250 for (
const std::pair<SDValue /*Op*/, int /*SubvectorIndex*/>
25251 &DemandedSubvector : DemandedSubvectors) {
25253 int Index = NumEltsExtracted * DemandedSubvector.second;
25256 DemandedSubvector.first, IndexC));
25259 "Should end up with either one or two ops");
25262 if (NewOps.
size() == 1)
25269 EVT NVT =
N->getValueType(0);
25271 uint64_t ExtIdx =
N->getConstantOperandVal(1);
25286 V.getConstantOperandVal(1)) &&
25306 unsigned InsIdx =
V.getConstantOperandVal(2);
25308 if (InsIdx <= ExtIdx && (ExtIdx + NumSubElts) <= (InsIdx + NumInsElts) &&
25311 V.getValueType().isFixedLengthVector())
25319 V.getOperand(0).getValueType().isVector() &&
25324 unsigned DestNumElts =
V.getValueType().getVectorMinNumElements();
25325 if ((SrcNumElts % DestNumElts) == 0) {
25326 unsigned SrcDestRatio = SrcNumElts / DestNumElts;
25333 V.getOperand(0), NewIndex);
25337 if ((DestNumElts % SrcNumElts) == 0) {
25338 unsigned DestSrcRatio = DestNumElts / SrcNumElts;
25343 if ((ExtIdx % DestSrcRatio) == 0) {
25344 unsigned IndexValScaled = ExtIdx / DestSrcRatio;
25351 V.getOperand(0), NewIndex);
25359 V.getOperand(0), NewIndex);
25369 EVT ConcatSrcVT =
V.getOperand(0).getValueType();
25371 "Concat and extract subvector do not change element type");
25372 assert((ExtIdx % ExtNumElts) == 0 &&
25373 "Extract index is not a multiple of the input vector length.");
25376 unsigned ConcatOpIdx = ExtIdx / ConcatSrcNumElts;
25382 return V.getOperand(ConcatOpIdx);
25390 ConcatSrcNumElts % ExtNumElts == 0) {
25391 unsigned NewExtIdx = ExtIdx - ConcatOpIdx * ConcatSrcNumElts;
25392 assert(NewExtIdx + ExtNumElts <= ConcatSrcNumElts &&
25393 "Trying to extract from >1 concat operand?");
25394 assert(NewExtIdx % ExtNumElts == 0 &&
25395 "Extract index is not a multiple of the input vector length.");
25398 V.getOperand(ConcatOpIdx), NewIndexC);
25410 EVT InVT =
V.getValueType();
25414 if (ExtractSize % EltSize == 0) {
25415 unsigned NumElems = ExtractSize / EltSize;
25418 NumElems == 1 ? EltVT
25426 if (NumElems == 1) {
25427 SDValue Src =
V->getOperand(IdxVal);
25428 if (EltVT != Src.getValueType())
25444 EVT SmallVT =
V.getOperand(1).getValueType();
25445 if (!NVT.
bitsEq(SmallVT))
25453 uint64_t InsIdx =
V.getConstantOperandVal(2);
25463 DAG.
getBitcast(
N->getOperand(0).getValueType(),
V.getOperand(0)),
25493 unsigned HalfNumElts = NumElts / 2;
25496 for (
unsigned i = 0; i != NumElts; ++i) {
25500 if ((Mask[i] % NumElts) >= HalfNumElts)
25502 int M = Mask[i] < (int)NumElts ? Mask[i] : Mask[i] - (
int)HalfNumElts;
25503 if (i < HalfNumElts)
25506 Mask1[i - HalfNumElts] = M;
25529 EVT VT =
N->getValueType(0);
25540 unsigned NumConcats = NumElts / NumElemsPerConcat;
25542 auto IsUndefMaskElt = [](
int i) {
return i == -1; };
25547 if (NumElemsPerConcat * 2 == NumElts && N1.
isUndef() &&
25548 llvm::all_of(Mask.slice(NumElemsPerConcat, NumElemsPerConcat),
25552 Mask.slice(0, NumElemsPerConcat));
25559 for (
unsigned I = 0;
I != NumConcats; ++
I) {
25560 unsigned Begin =
I * NumElemsPerConcat;
25561 ArrayRef<int> SubMask = Mask.slice(Begin, NumElemsPerConcat);
25570 for (
int i = 0; i != (int)NumElemsPerConcat; ++i) {
25571 if (IsUndefMaskElt(SubMask[i]))
25573 if ((SubMask[i] % (
int)NumElemsPerConcat) != i)
25575 int EltOpIdx = SubMask[i] / NumElemsPerConcat;
25576 if (0 <= OpIdx && EltOpIdx != OpIdx)
25580 assert(0 <= OpIdx &&
"Unknown concat_vectors op");
25634 bool IsSplat =
false;
25635 auto *BV0 = dyn_cast<BuildVectorSDNode>(N0);
25636 auto *BV1 = dyn_cast<BuildVectorSDNode>(N1);
25638 if (
SDValue Splat0 = BV0->getSplatValue())
25639 IsSplat = (Splat0 == BV1->getSplatValue());
25643 for (
int M : SVN->
getMask()) {
25646 int Idx = M < (int)NumElts ? M : M - NumElts;
25647 SDValue &S = (M < (int)NumElts ? N0 : N1);
25649 Op = S.getOperand(
Idx);
25664 if (!IsSplat && !DuplicateOps.
insert(
Op).second)
25675 SVT = (SVT.
bitsLT(
Op.getValueType()) ?
Op.getValueType() : SVT);
25691 unsigned Opcode,
EVT VT, std::function<
bool(
unsigned)>
Match,
25693 bool LegalOperations) {
25698 return std::nullopt;
25706 for (
unsigned Scale = 2; Scale < NumElts; Scale *= 2) {
25708 if (NumElts % Scale != 0)
25722 return std::nullopt;
25731 bool LegalOperations) {
25741 Mask = SVN->
getMask()](
unsigned Scale) {
25742 for (
unsigned i = 0; i != NumElts; ++i) {
25745 if ((i % Scale) == 0 && Mask[i] == (int)(i / Scale))
25757 Opcode, VT, isAnyExtend, DAG, TLI,
true, LegalOperations);
25769 bool LegalOperations) {
25770 bool LegalTypes =
true;
25782 auto ForEachDecomposedIndice = [NumElts, &Mask](
auto Fn) {
25783 for (
int &Indice : Mask) {
25786 int OpIdx = (
unsigned)Indice < NumElts ? 0 : 1;
25787 int OpEltIdx = (
unsigned)Indice < NumElts ? Indice : Indice - NumElts;
25788 Fn(Indice, OpIdx, OpEltIdx);
25793 std::array<APInt, 2> OpsDemandedElts;
25794 for (
APInt &OpDemandedElts : OpsDemandedElts)
25796 ForEachDecomposedIndice(
25797 [&OpsDemandedElts](
int &Indice,
int OpIdx,
int OpEltIdx) {
25798 OpsDemandedElts[OpIdx].setBit(OpEltIdx);
25802 std::array<APInt, 2> OpsKnownZeroElts;
25803 for (
auto I :
zip(SVN->
ops(), OpsDemandedElts, OpsKnownZeroElts))
25811 bool HadZeroableElts =
false;
25812 ForEachDecomposedIndice([&OpsKnownZeroElts, &HadZeroableElts](
25813 int &Indice,
int OpIdx,
int OpEltIdx) {
25814 if (OpsKnownZeroElts[OpIdx][OpEltIdx]) {
25816 HadZeroableElts =
true;
25824 if (!HadZeroableElts)
25832 Mask.size() % ScaledMask.
size() == 0 &&
"Unexpected mask widening.");
25833 int Prescale = Mask.size() / ScaledMask.
size();
25835 NumElts = ScaledMask.
size();
25836 EltSizeInBits *= Prescale;
25848 auto isZeroExtend = [NumElts, &ScaledMask](
unsigned Scale) {
25849 assert(Scale >= 2 && Scale <= NumElts && NumElts % Scale == 0 &&
25850 "Unexpected mask scaling factor.");
25852 for (
unsigned SrcElt = 0, NumSrcElts = NumElts / Scale;
25853 SrcElt != NumSrcElts; ++SrcElt) {
25856 assert(MaskChunk.
size() == Scale &&
"Unexpected mask size.");
25857 Mask = Mask.drop_front(MaskChunk.
size());
25860 if (
int FirstIndice = MaskChunk[0]; (
unsigned)FirstIndice != SrcElt)
25865 [](
int Indice) { return Indice == -2; }))
25868 assert(Mask.empty() &&
"Did not process the whole mask?");
25873 for (
bool Commuted : {
false,
true}) {
25878 Opcode, PrescaledVT, isZeroExtend, DAG, TLI, LegalTypes,
25914 if (ExtDstSizeInBits % ExtSrcSizeInBits != 0)
25916 unsigned ExtScale = ExtDstSizeInBits / ExtSrcSizeInBits;
25921 auto isTruncate = [&Mask, &NumElts](
unsigned Scale) {
25922 for (
unsigned i = 0; i != NumElts; ++i) {
25925 if ((i * Scale) < NumElts && Mask[i] == (int)(i * Scale))
25935 if (EltSizeInBits != ExtSrcSizeInBits)
25940 if (isTruncate(ExtScale))
25963 APInt DemandedElts(NumElts, 0);
25967 assert((
unsigned)
Idx < NumElts &&
"Out-of-bounds shuffle indice?");
25970 assert(DemandedElts.
popcount() > 1 &&
"Is a splat shuffle already?");
25975 std::optional<unsigned> MinNonUndefIdx;
25977 if (
Idx < 0 || UndefElts[
Idx])
25979 MinNonUndefIdx = std::min<unsigned>(
Idx, MinNonUndefIdx.value_or(~0U));
25981 if (!MinNonUndefIdx)
25983 assert(*MinNonUndefIdx < NumElts &&
"Expected valid element index.");
25985 for (
int &
Idx : SplatMask) {
25990 Idx = UndefElts[
Idx] ? -1 : *MinNonUndefIdx;
25992 assert(SplatMask != Shuf->
getMask() &&
"Expected mask to change!");
26010 assert(ShufMask.
size() == SplatMask.
size() &&
"Mask length mismatch");
26028 auto CanSimplifyToExistingSplat = [](
ArrayRef<int> UserMask,
26030 for (
unsigned i = 0, e = UserMask.
size(); i != e; ++i)
26031 if (UserMask[i] != -1 && SplatMask[i] == -1 &&
26032 SplatMask[UserMask[i]] != -1)
26036 if (CanSimplifyToExistingSplat(ShufMask, SplatMask))
26042 for (
int Idx : ShufMask)
26055 bool LegalOperations) {
26072 if (VTLanes <= InLanes || VTLanes % InLanes != 0 ||
26073 (LegalOperations &&
26076 int Factor = VTLanes / InLanes;
26103 auto *InnerShuf = dyn_cast<ShuffleVectorSDNode>(OuterShuf->
getOperand(0));
26104 if (!InnerShuf || !InnerShuf->getOperand(1).isUndef())
26109 unsigned NumElts = OuterMask.
size();
26110 assert(NumElts == InnerMask.
size() &&
"Mask length mismatch");
26112 int SplatIndex = -1;
26113 for (
unsigned i = 0; i != NumElts; ++i) {
26115 int OuterMaskElt = OuterMask[i];
26116 if (OuterMaskElt == -1)
26120 int InnerMaskElt = InnerMask[OuterMaskElt];
26121 if (InnerMaskElt == -1)
26125 if (SplatIndex == -1)
26126 SplatIndex = InnerMaskElt;
26129 if (SplatIndex != InnerMaskElt)
26132 CombinedMask[i] = InnerMaskElt;
26134 assert((
all_of(CombinedMask, [](
int M) {
return M == -1; }) ||
26136 "Expected a splat mask");
26140 assert(VT == InnerShuf->getValueType(0) &&
"Expected matching shuffle types");
26145 InnerShuf->getOperand(1), CombinedMask);
26153 int MaskSize = Mask.size();
26154 int EltFromOp0 = -1;
26159 for (
int i = 0; i != MaskSize; ++i) {
26160 if (Mask[i] >= 0 && Mask[i] < MaskSize) {
26162 if (EltFromOp0 != -1)
26165 }
else if (Mask[i] != i + MaskSize) {
26185 if (ShufOp0Index == -1) {
26189 if (ShufOp0Index == -1)
26193 Mask = CommutedMask;
26201 assert(Mask[ShufOp0Index] >= 0 && Mask[ShufOp0Index] < (
int)Mask.size() &&
26202 "Shuffle mask value must be from operand 0");
26220 Op1, Elt, NewInsIndex);
26232 auto *Shuf0 = dyn_cast<ShuffleVectorSDNode>(Shuf->
getOperand(0));
26238 for (
int i = 0, e = (
int)Mask.size(); i != e; ++i) {
26242 assert(Mask[i] >= 0 && Mask[i] < e &&
"Unexpected shuffle mask value");
26246 if (Mask0[Mask[i]] != Mask0[i])
26255 EVT VT =
N->getValueType(0);
26280 bool Changed =
false;
26282 for (
unsigned i = 0; i != NumElts; ++i) {
26284 if (
Idx >= (
int)NumElts) {
26333 if (
auto *
Idx = dyn_cast<ConstantSDNode>(N0.
getOperand(2)))
26334 if (
Idx->getAPIntValue() == SplatIndex)
26360 SDValue ConvInput =
V->getOperand(0);
26367 assert(
V->getNumOperands() == NumElts &&
26368 "BUILD_VECTOR has wrong number of operands");
26370 bool AllSame =
true;
26371 for (
unsigned i = 0; i != NumElts; ++i) {
26372 if (!
V->getOperand(i).isUndef()) {
26373 Base =
V->getOperand(i);
26378 if (!
Base.getNode())
26380 for (
unsigned i = 0; i != NumElts; ++i) {
26381 if (
V->getOperand(i) !=
Base) {
26392 SDValue Splatted =
V->getOperand(SplatIndex);
26396 for (
unsigned i = 0; i != NumElts; ++i) {
26405 if (
V->getValueType(0) != VT)
26444 int HalfNumElts = (int)NumElts / 2;
26446 for (
unsigned i = 0; i != NumElts; ++i) {
26448 if (
Idx >= HalfNumElts) {
26449 assert(
Idx < (
int)NumElts &&
"Shuffle mask chooses undef op");
26450 Idx -= HalfNumElts;
26471 EVT SubVT =
RHS.getOperand(0).getValueType();
26472 int NumSubVecs =
RHS.getNumOperands();
26474 assert((NumElts % NumSubElts) == 0 &&
"Subvector mismatch");
26479 if (
all_of(Mask, [NumElts](
int M) {
return M < (int)NumElts; }))
26485 for (
int SubVec = 0; SubVec != NumSubVecs; ++SubVec) {
26486 for (
int SubIdx = 0; SubIdx != (int)NumElts; SubIdx += NumSubElts) {
26488 std::iota(InsertionMask.begin(), InsertionMask.end(), 0);
26491 std::iota(InsertionMask.begin() + SubIdx,
26492 InsertionMask.begin() + SubIdx + NumSubElts,
26493 NumElts + (SubVec * NumSubElts));
26496 bool MatchingShuffle =
true;
26497 for (
int i = 0; i != (int)NumElts; ++i) {
26498 int ExpectIdx = InsertionMask[i];
26499 int ActualIdx =
Mask[i];
26500 if (0 <= ActualIdx && ExpectIdx != ActualIdx) {
26501 MatchingShuffle =
false;
26506 if (MatchingShuffle)
26508 RHS.getOperand(SubVec),
26516 if (
SDValue InsertN1 = ShuffleToInsert(N0, N1, Mask))
26521 if (
SDValue InsertN0 = ShuffleToInsert(N1, N0, CommuteMask))
26529 bool IsInLaneMask =
true;
26534 for (
int I = 0;
I != (int)NumElts; ++
I) {
26538 ClearMask[
I] =
M ==
I ?
I : (
I + NumElts);
26539 IsInLaneMask &= (
M ==
I) || (M == (
int)(
I + NumElts));
26541 APInt &Demanded =
M < (int)NumElts ? DemandedLHS : DemandedRHS;
26542 Demanded.
setBit(M % NumElts);
26546 if (!IsInLaneMask && (!DemandedLHS.
isZero() || !DemandedRHS.
isZero()) &&
26561 for (
int I = 0;
I != (int)NumElts; ++
I)
26563 AndMask[
I] =
Mask[
I] ==
I ? AllOnesElt : ZeroElt;
26600 EVT ScaleVT = SVT.
bitsLT(InnerSVT) ? VT : InnerVT;
26618 for (
int M : OuterMask)
26619 NewMask.
push_back(M < 0 ? -1 : InnerMask[M]);
26650 auto MergeInnerShuffle =
26657 if (OtherSVN->isSplat())
26663 for (
unsigned i = 0; i != NumElts; ++i) {
26664 int Idx = SVN->getMaskElt(i);
26672 Idx = (
Idx < (int)NumElts) ? (
Idx + NumElts) : (
Idx - NumElts);
26675 if (
Idx < (
int)NumElts) {
26678 Idx = OtherSVN->getMaskElt(
Idx);
26684 CurrentVec = (
Idx < (int)NumElts) ? OtherSVN->
getOperand(0)
26693 Mask.push_back(-1);
26700 if (!SV0.getNode() || SV0 == CurrentVec) {
26707 if (!SV1.getNode() || SV1 == CurrentVec) {
26711 Mask.push_back(
Idx + NumElts);
26717 if (
auto *CurrentSVN = dyn_cast<ShuffleVectorSDNode>(CurrentVec)) {
26718 int InnerIdx = CurrentSVN->getMaskElt(
Idx);
26719 if (InnerIdx < 0) {
26720 Mask.push_back(-1);
26723 SDValue InnerVec = (InnerIdx < (int)NumElts)
26727 Mask.push_back(-1);
26730 InnerIdx %= NumElts;
26731 if (InnerVec == SV0) {
26732 Mask.push_back(InnerIdx);
26735 if (InnerVec == SV1) {
26736 Mask.push_back(InnerIdx + NumElts);
26755 if (TLI.isShuffleMaskLegal(Mask, VT))
26760 return TLI.isShuffleMaskLegal(Mask, VT);
26772 assert(N1->getOperand(0).getValueType() == VT &&
26773 "Shuffle types don't match");
26777 bool HasSameOp0 = N0 == SV0;
26778 bool IsSV1Undef = SV1.
isUndef();
26779 if (HasSameOp0 || IsSV1Undef || N0 == SV1)
26788 cast<ShuffleVectorSDNode>(N0)->isSplat() &&
26789 !cast<ShuffleVectorSDNode>(N1)->isSplat()) {
26800 for (
int i = 0; i != 2; ++i) {
26802 N->isOnlyUserOf(
N->getOperand(i).getNode())) {
26805 auto *OtherSV = cast<ShuffleVectorSDNode>(
N->getOperand(i));
26806 assert(OtherSV->getOperand(0).getValueType() == VT &&
26807 "Shuffle types don't match");
26811 if (MergeInnerShuffle(i != 0, SVN, OtherSV,
N->getOperand(1 - i), TLI,
26819 SV1 ? SV1 : DAG.
getUNDEF(VT), Mask);
26829 if (TLI.isBinOp(SrcOpcode) &&
N->isOnlyUserOf(N0.
getNode()) &&
26831 (SrcOpcode == N1.getOpcode() &&
N->isOnlyUserOf(N1.getNode())))) {
26849 SDValue InnerN = Commute ? N1 : N0;
26850 SDValue Op0 = LeftOp ? Op00 : Op01;
26851 SDValue Op1 = LeftOp ? Op10 : Op11;
26856 auto *SVN0 = dyn_cast<ShuffleVectorSDNode>(Op0);
26858 MergeInnerShuffle(Commute, SVN, SVN0, Op1, TLI, SV0, SV1,
26860 (
llvm::any_of(SVN0->getMask(), [](
int M) { return M < 0; }) ||
26866 bool MergedLeft =
false;
26869 if (CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
false) ||
26870 CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
true)) {
26873 LeftMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
26874 LeftSV0 = Op00, LeftSV1 = Op10;
26877 bool MergedRight =
false;
26880 if (CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
false) ||
26881 CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
true)) {
26882 MergedRight =
true;
26884 RightMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
26885 RightSV0 = Op01, RightSV1 = Op11;
26888 if (MergedLeft || MergedRight) {
26891 VT,
DL, LeftSV0 ? LeftSV0 : DAG.
getUNDEF(VT),
26892 LeftSV1 ? LeftSV1 : DAG.
getUNDEF(VT), LeftMask);
26894 VT,
DL, RightSV0 ? RightSV0 : DAG.
getUNDEF(VT),
26895 RightSV1 ? RightSV1 : DAG.
getUNDEF(VT), RightMask);
26896 return DAG.
getNode(SrcOpcode,
DL, VT, LHS, RHS);
26917 EVT VT =
N->getValueType(0);
26927 unsigned Opcode =
Scalar.getOpcode();
26929 if (
Scalar.hasOneUse() &&
Scalar->getNumValues() == 1 &&
26930 TLI.isBinOp(Opcode) &&
Scalar.getValueType() == VecEltVT &&
26931 Scalar.getOperand(0).getValueType() == VecEltVT &&
26932 Scalar.getOperand(1).getValueType() == VecEltVT &&
26933 Scalar->isOnlyUserOf(
Scalar.getOperand(0).getNode()) &&
26934 Scalar->isOnlyUserOf(
Scalar.getOperand(1).getNode()) &&
26939 for (
int i : {0, 1}) {
26943 auto *
C = dyn_cast<ConstantSDNode>(
Scalar.getOperand(i ? 0 : 1));
26950 if (TLI.isShuffleMaskLegal(ShufMask, VT)) {
26965 !
Scalar.getOperand(0).getValueType().isFixedLengthVector())
26969 if (VecEltVT !=
Scalar.getValueType() &&
26975 auto *ExtIndexC = dyn_cast<ConstantSDNode>(
Scalar.getOperand(1));
26983 if (VecEltVT == SrcVT.
getScalarType() && VTNumElts <= SrcNumElts) {
26986 Mask[0] = ExtIndexC->getZExtValue();
26987 SDValue LegalShuffle = TLI.buildLegalVectorShuffle(
26994 return LegalShuffle;
26997 if (VTNumElts != SrcNumElts) {
27010 EVT VT =
N->getValueType(0);
27014 uint64_t InsIdx =
N->getConstantOperandVal(2);
27114 if ((N0.
isUndef() || N0SrcSVT == N1SrcSVT) &&
27126 }
else if ((N1SrcSVT.
getSizeInBits() % EltSizeInBits) == 0) {
27149 if (InsIdx < OtherIdx) {
27153 AddToWorklist(NewOp.
getNode());
27167 Ops[InsIdx / Factor] = N1;
27189 auto Op =
N->getOpcode();
27191 "opcode should be FP16_TO_FP or BF16_TO_FP.");
27207 N->getValueType(0), {N0});
27223 return visitFP16_TO_FP(
N);
27229 unsigned Opcode =
N->getOpcode();
27247 if (!TLI.isOperationLegalOrCustom(Opcode, VT) &&
27248 TLI.isOperationLegalOrCustom(NewOpcode, VT) &&
27250 return DAG.
getNode(NewOpcode,
SDLoc(
N),
N->getValueType(0), N0);
27263 return DAG.
getNode(Opcode,
SDLoc(
N),
N->getValueType(0), Subvec);
27286 if (
SDValue Fused = visitFSUBForFMACombine<VPMatchContext>(
N)) {
27287 AddToWorklist(Fused.getNode());
27295 if (
N->getOpcode() == ISD::VP_GATHER)
27296 if (
SDValue SD = visitVPGATHER(
N))
27299 if (
N->getOpcode() == ISD::VP_SCATTER)
27300 if (
SDValue SD = visitVPSCATTER(
N))
27303 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_LOAD)
27304 if (
SDValue SD = visitVP_STRIDED_LOAD(
N))
27307 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_STORE)
27308 if (
SDValue SD = visitVP_STRIDED_STORE(
N))
27314 bool AreAllEltsDisabled =
false;
27318 AreAllEltsDisabled |=
27322 if (!AreAllEltsDisabled) {
27323 switch (
N->getOpcode()) {
27325 return visitVP_FADD(
N);
27327 return visitVP_FSUB(
N);
27329 return visitFMA<VPMatchContext>(
N);
27330 case ISD::VP_SELECT:
27331 return visitVP_SELECT(
N);
27333 return visitMUL<VPMatchContext>(
N);
27335 return foldSubCtlzNot<VPMatchContext>(
N, DAG);
27344 return DAG.
getUNDEF(
N->getValueType(0));
27348 if (
const auto *MemSD = dyn_cast<MemSDNode>(
N)) {
27349 if (MemSD->writeMem())
27350 return MemSD->getChain();
27351 return CombineTo(
N, DAG.
getUNDEF(
N->getValueType(0)), MemSD->getChain());
27356 return N->getOperand(0);
27364 EVT MemVT = cast<FPStateAccessSDNode>(
N)->getMemoryVT();
27369 for (
auto *U :
Ptr->users()) {
27372 if (
auto *Ld = dyn_cast<LoadSDNode>(U)) {
27373 if (LdNode && LdNode != Ld)
27388 if (
U.getResNo() == 0) {
27389 if (
auto *St = dyn_cast<StoreSDNode>(
U.getUser())) {
27407 CombineTo(StNode, Res,
false);
27414 EVT MemVT = cast<FPStateAccessSDNode>(
N)->getMemoryVT();
27418 for (
auto *U :
Ptr->users()) {
27421 if (
auto *St = dyn_cast<StoreSDNode>(U)) {
27422 if (StNode && StNode != St)
27437 auto *LdNode = dyn_cast<LoadSDNode>(StValue);
27458 EVT VT =
N->getValueType(0);
27465 if (LegalOperations)
27471 EVT RVT =
RHS.getValueType();
27472 unsigned NumElts =
RHS.getNumOperands();
27477 auto BuildClearMask = [&](
int Split) {
27478 int NumSubElts = NumElts *
Split;
27482 for (
int i = 0; i != NumSubElts; ++i) {
27483 int EltIdx = i /
Split;
27484 int SubIdx = i %
Split;
27494 if (
auto *Cst = dyn_cast<ConstantSDNode>(Elt))
27495 Bits = Cst->getAPIntValue();
27496 else if (
auto *CstFP = dyn_cast<ConstantFPSDNode>(Elt))
27503 Bits =
Bits.extractBits(NumSubBits, (Split - SubIdx - 1) * NumSubBits);
27505 Bits =
Bits.extractBits(NumSubBits, SubIdx * NumSubBits);
27507 if (
Bits.isAllOnes())
27509 else if (Bits == 0)
27518 if (!TLI.isVectorClearMaskLegal(Indices, ClearVT))
27532 for (
int Split = 1;
Split <= MaxSplit; ++
Split)
27534 if (
SDValue S = BuildClearMask(Split))
27543 const SDLoc &
DL,
bool LegalTypes) {
27546 unsigned Opcode =
N->getOpcode();
27547 EVT VT =
N->getValueType(0);
27554 int Index0, Index1;
27561 if (!Src0 || !Src1 || Index0 != Index1 ||
27588 for (
auto [
X,
Y] :
zip(EltsX, EltsY))
27604 EVT VT =
N->getValueType(0);
27605 assert(VT.
isVector() &&
"SimplifyVCastOp only works on vectors!");
27607 unsigned Opcode =
N->getOpcode();
27637 EVT VT =
N->getValueType(0);
27638 assert(VT.
isVector() &&
"SimplifyVBinOp only works on vectors!");
27642 unsigned Opcode =
N->getOpcode();
27653 auto *Shuf0 = dyn_cast<ShuffleVectorSDNode>(LHS);
27654 auto *Shuf1 = dyn_cast<ShuffleVectorSDNode>(RHS);
27655 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
27656 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
27659 RHS.getOperand(0), Flags);
27671 Shuf0->hasOneUse() && Shuf0->getOperand(1).isUndef() &&
27680 Shuf1->hasOneUse() && Shuf1->getOperand(1).isUndef() &&
27696 LHS.getOperand(2) ==
RHS.getOperand(2) &&
27701 EVT NarrowVT =
X.getValueType();
27702 if (NarrowVT ==
Y.getValueType() &&
27704 LegalOperations)) {
27717 return Op.isUndef() ||
27718 ISD::isBuildVectorOfConstantSDNodes(Op.getNode());
27727 if (ConcatWithConstantOrUndef(LHS) && ConcatWithConstantOrUndef(RHS) &&
27729 EVT NarrowVT =
LHS.getOperand(0).getValueType();
27730 if (NarrowVT ==
RHS.getOperand(0).getValueType() &&
27732 unsigned NumOperands =
LHS.getNumOperands();
27734 for (
unsigned i = 0; i != NumOperands; ++i) {
27737 RHS.getOperand(i)));
27753 "First argument must be a SetCC node!");
27756 cast<CondCodeSDNode>(N0.
getOperand(2))->get());
27761 if (
SCC.getNode()) {
27768 SCC.getOperand(0),
SCC.getOperand(1),
27769 SCC.getOperand(4), Flags);
27770 AddToWorklist(
SETCC.getNode());
27772 SCC.getOperand(2),
SCC.getOperand(3));
27787bool DAGCombiner::SimplifySelectOps(
SDNode *TheSelect,
SDValue LHS,
27800 CC = cast<CondCodeSDNode>(TheSelect->
getOperand(4))->get();
27807 CC = cast<CondCodeSDNode>(
Cmp.getOperand(2))->get();
27808 CmpLHS =
Cmp.getOperand(0);
27812 if (Zero &&
Zero->isZero() &&
27816 CombineTo(TheSelect, Sqrt);
27826 if (
LHS.getOpcode() !=
RHS.getOpcode() ||
27839 if (
LHS.getOperand(0) !=
RHS.getOperand(0) ||
27883 Visited.
insert(TheSelect);
27962 CombineTo(TheSelect, Load);
27966 CombineTo(
LHS.getNode(),
Load.getValue(0),
Load.getValue(1));
27967 CombineTo(
RHS.getNode(),
Load.getValue(0),
Load.getValue(1));
28007 auto *N2C = dyn_cast<ConstantSDNode>(N2.
getNode());
28008 if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue() - 1)) == 0)) {
28009 unsigned ShCt = XType.
getSizeInBits() - N2C->getAPIntValue().logBase2() - 1;
28013 AddToWorklist(Shift.
getNode());
28015 if (XType.
bitsGT(AType)) {
28017 AddToWorklist(Shift.
getNode());
28021 Shift = DAG.
getNOT(
DL, Shift, AType);
28033 AddToWorklist(Shift.
getNode());
28035 if (XType.
bitsGT(AType)) {
28037 AddToWorklist(Shift.
getNode());
28041 Shift = DAG.
getNOT(
DL, Shift, AType);
28104 EVT VT =
N->getValueType(0);
28112 EVT IntVT =
Int.getValueType();
28126 SignMask = ~SignMask;
28132 SignMask = ~SignMask;
28137 AddToWorklist(
Int.getNode());
28145SDValue DAGCombiner::convertSelectOfFPConstantsToLoadOffset(
28153 auto *TV = dyn_cast<ConstantFPSDNode>(N2);
28154 auto *FV = dyn_cast<ConstantFPSDNode>(N3);
28161 TLI.
isFPImmLegal(TV->getValueAPF(), TV->getValueType(0), ForCodeSize) ||
28162 TLI.
isFPImmLegal(FV->getValueAPF(), FV->getValueType(0), ForCodeSize))
28167 if (!TV->hasOneUse() && !FV->hasOneUse())
28171 const_cast<ConstantFP*
>(TV->getConstantFPValue()) };
28179 Align Alignment = cast<ConstantPoolSDNode>(CPIdx)->getAlign();
28188 AddToWorklist(
Cond.getNode());
28190 AddToWorklist(CstOffset.
getNode());
28192 AddToWorklist(CPIdx.
getNode());
28202 bool NotExtCompare) {
28204 if (N2 == N3)
return N2;
28209 auto *N1C = dyn_cast<ConstantSDNode>(N1.
getNode());
28210 auto *N2C = dyn_cast<ConstantSDNode>(N2.
getNode());
28211 auto *N3C = dyn_cast<ConstantSDNode>(N3.
getNode());
28215 AddToWorklist(
SCC.getNode());
28216 if (
auto *SCCC = dyn_cast<ConstantSDNode>(SCC)) {
28219 return !(SCCC->isZero()) ? N2 : N3;
28224 convertSelectOfFPConstantsToLoadOffset(
DL, N0, N1, N2, N3,
CC))
28227 if (
SDValue V = foldSelectCCToShiftAnd(
DL, N0, N1, N2, N3,
CC))
28239 auto *ConstAndRHS = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
28240 if (ConstAndRHS && ConstAndRHS->getAPIntValue().popcount() == 1) {
28242 const APInt &AndMask = ConstAndRHS->getAPIntValue();
28260 bool Fold = N2C &&
isNullConstant(N3) && N2C->getAPIntValue().isPowerOf2();
28261 bool Swap = N3C &&
isNullConstant(N2) && N3C->getAPIntValue().isPowerOf2();
28263 if ((Fold || Swap) &&
28275 if (NotExtCompare && N2C->isOne())
28288 AddToWorklist(
SCC.getNode());
28289 AddToWorklist(Temp.
getNode());
28294 unsigned ShCt = N2C->getAPIntValue().logBase2();
28319 if (
auto *ValueOnZeroC = dyn_cast<ConstantSDNode>(ValueOnZero)) {
28341 if (!NotExtCompare && N1C && N2C && N3C &&
28342 N2C->getAPIntValue() == ~N3C->getAPIntValue() &&
28357 if (
SDValue ABD = foldSelectToABD(N0, N1, N2, N3,
CC,
DL))
28366 bool foldBooleans) {
28368 DagCombineInfo(DAG, Level,
false,
this);
28466 bool AssumeNonZero) {
28469 auto PeekThroughCastsAndTrunc = [](
SDValue V) {
28471 switch (V.getOpcode()) {
28474 V = V.getOperand(0);
28485 Op = PeekThroughCastsAndTrunc(
Op);
28491 if (
C->isZero() ||
C->isOpaque())
28494 if (
C->getAPIntValue().isPowerOf2()) {
28510 for (
const APInt &Pow2 : Pow2Constants)
28519 auto CastToVT = [&](
EVT NewVT,
SDValue ToCast) {
28520 ToCast = PeekThroughCastsAndTrunc(ToCast);
28521 EVT CurVT = ToCast.getValueType();
28522 if (NewVT == CurVT)
28534 if (AssumeNonZero ||
Op->getFlags().hasNoUnsignedWrap() ||
28537 Depth + 1, AssumeNonZero))
28539 CastToVT(VT,
Op.getOperand(1)));
28546 Depth + 1, AssumeNonZero))
28548 Depth + 1, AssumeNonZero))
28549 return DAG.
getSelect(
DL, VT,
Op.getOperand(0), LogX, LogY);
28564 return DAG.
getNode(
Op.getOpcode(),
DL, VT, LogX, LogY);
28573 bool KnownNonZero,
bool InexpensiveOnly,
28574 std::optional<EVT> OutVT) {
28575 EVT VT = OutVT ? *OutVT :
V.getValueType();
28576 SDValue InexpensiveLogBase2 =
28579 return InexpensiveLogBase2;
28601 EVT VT =
Op.getValueType();
28609 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
28616 AddToWorklist(Est.getNode());
28624 for (
int i = 0; i < Iterations; ++i) {
28627 if (i == Iterations - 1) {
28629 AddToWorklist(MulEst.
getNode());
28633 AddToWorklist(NewEst.
getNode());
28636 (i == Iterations - 1 ?
N : FPOne), NewEst, Flags);
28637 AddToWorklist(NewEst.
getNode());
28640 AddToWorklist(NewEst.
getNode());
28643 AddToWorklist(Est.getNode());
28648 AddToWorklist(Est.getNode());
28664 unsigned Iterations,
28676 for (
unsigned i = 0; i < Iterations; ++i) {
28696 unsigned Iterations,
28709 for (
unsigned i = 0; i < Iterations; ++i) {
28718 if (Reciprocal || (i + 1) < Iterations) {
28741 EVT VT =
Op.getValueType();
28749 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
28756 bool UseOneConstNR =
false;
28760 AddToWorklist(Est.
getNode());
28762 if (Iterations > 0)
28763 Est = UseOneConstNR
28764 ? buildSqrtNROneConst(
Op, Est, Iterations, Flags, Reciprocal)
28765 : buildSqrtNRTwoConst(
Op, Est, Iterations,
Flags, Reciprocal);
28785 return buildSqrtEstimateImpl(
Op, Flags,
true);
28789 return buildSqrtEstimateImpl(
Op, Flags,
false);
28793bool DAGCombiner::mayAlias(
SDNode *Op0,
SDNode *Op1)
const {
28795 struct MemUseCharacteristics {
28804 auto getCharacteristics = [](
SDNode *
N) -> MemUseCharacteristics {
28805 if (
const auto *LSN = dyn_cast<LSBaseSDNode>(
N)) {
28807 if (
auto *
C = dyn_cast<ConstantSDNode>(LSN->getOffset()))
28810 ? -1 *
C->getSExtValue()
28813 return {LSN->isVolatile(), LSN->isAtomic(),
28814 LSN->getBasePtr(),
Offset ,
28817 if (
const auto *LN = cast<LifetimeSDNode>(
N))
28821 (LN->hasOffset()) ? LN->getOffset() : 0,
28834 MemUseCharacteristics MUC0 = getCharacteristics(Op0),
28835 MUC1 = getCharacteristics(Op1);
28838 if (MUC0.BasePtr.getNode() && MUC0.BasePtr == MUC1.BasePtr &&
28839 MUC0.Offset == MUC1.Offset)
28843 if (MUC0.IsVolatile && MUC1.IsVolatile)
28848 if (MUC0.IsAtomic && MUC1.IsAtomic)
28851 if (MUC0.MMO && MUC1.MMO) {
28852 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
28853 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
28859 if ((MUC0.NumBytes.hasValue() && MUC0.NumBytes.isScalable() &&
28860 MUC0.Offset != 0) ||
28861 (MUC1.NumBytes.hasValue() && MUC1.NumBytes.isScalable() &&
28873 if (!MUC0.MMO || !MUC1.MMO)
28879 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
28880 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
28888 int64_t SrcValOffset0 = MUC0.MMO->getOffset();
28889 int64_t SrcValOffset1 = MUC1.MMO->getOffset();
28890 Align OrigAlignment0 = MUC0.MMO->getBaseAlign();
28891 Align OrigAlignment1 = MUC1.MMO->getBaseAlign();
28895 if (OrigAlignment0 == OrigAlignment1 && SrcValOffset0 != SrcValOffset1 &&
28901 int64_t OffAlign0 = SrcValOffset0 % OrigAlignment0.
value();
28902 int64_t OffAlign1 = SrcValOffset1 % OrigAlignment1.
value();
28906 if ((OffAlign0 +
static_cast<int64_t
>(
28908 (OffAlign1 +
static_cast<int64_t
>(
28922 if (
UseAA && BatchAA && MUC0.MMO->getValue() && MUC1.MMO->getValue() &&
28925 (!Size0.
isScalable() || SrcValOffset0 == 0) &&
28926 (!Size1.
isScalable() || SrcValOffset1 == 0)) {
28928 int64_t MinOffset = std::min(SrcValOffset0, SrcValOffset1);
28951void DAGCombiner::GatherAllAliases(
SDNode *
N,
SDValue OriginalChain,
28958 const bool IsLoad = isa<LoadSDNode>(
N) && cast<LoadSDNode>(
N)->isSimple();
28962 unsigned Depth = 0;
28965 auto ImproveChain = [&](
SDValue &
C) ->
bool {
28966 switch (
C.getOpcode()) {
28975 bool IsOpLoad = isa<LoadSDNode>(
C.getNode()) &&
28976 cast<LSBaseSDNode>(
C.getNode())->isSimple();
28977 if ((IsLoad && IsOpLoad) || !
mayAlias(
N,
C.getNode())) {
28979 C =
C.getOperand(0);
28988 C =
C.getOperand(0);
28997 C =
C.getOperand(0);
29010 while (!Chains.
empty()) {
29044 if (ImproveChain(Chain)) {
29066 GatherAllAliases(
N, OldChain, Aliases);
29069 if (Aliases.
empty())
29073 if (Aliases.
size() == 1)
29093bool DAGCombiner::parallelizeChainedStores(
StoreSDNode *St) {
29110 if (!
BasePtr.getBase().getNode())
29114 if (
BasePtr.getBase().isUndef())
29132 if (Chain->getMemoryVT().isScalableVector())
29136 if (!
SDValue(Chain, 0)->hasOneUse())
29139 if (!Chain->isSimple() || Chain->isIndexed())
29148 int64_t
Length = (Chain->getMemoryVT().getSizeInBits() + 7) / 8;
29151 auto I = Intervals.find(
Offset);
29156 if (
I != Intervals.begin() && (--
I).stop() <=
Offset)
29165 if (ChainedStores.
empty())
29172 for (
unsigned I = ChainedStores.
size();
I;) {
29174 SDValue BetterChain = FindBetterChain(S, NewChain);
29178 ChainedStores[
I] = S;
29182 SDValue BetterChain = FindBetterChain(St, NewChain);
29197 auto hasImprovedChain = [&](
SDValue ST) ->
bool {
29198 return ST->getOperand(0) != NewChain;
29200 bool AddNewChain =
llvm::all_of(TFOps, hasImprovedChain);
29210 AddToWorklist(
Op.getNode());
29211 AddToWorklist(STChain);
29215bool DAGCombiner::findBetterNeighborChains(
StoreSDNode *St) {
29222 if (!
BasePtr.getBase().getNode())
29226 if (
BasePtr.getBase().isUndef())
29230 if (parallelizeChainedStores(St))
29235 if (St->
getChain() != BetterChain) {
29236 replaceStoreChain(St, BetterChain);
29246 DAGCombiner(*
this, BatchAA, OptLevel).Run(Level);
static bool mayAlias(MachineInstr &MIa, SmallVectorImpl< MachineInstr * > &MemInsns, AliasAnalysis *AA)
static cl::opt< bool > UseAA("aarch64-use-aa", cl::init(true), cl::desc("Enable the use of AA during codegen."))
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
AMDGPU Register Bank Select
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
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 foldBitOrderCrossLogicOp(SDNode *N, SelectionDAG &DAG)
static SDValue tryToFoldExtendOfConstant(SDNode *N, const SDLoc &DL, const TargetLowering &TLI, SelectionDAG &DAG, bool LegalTypes)
Try to fold a sext/zext/aext dag node into a ConstantSDNode or a build_vector of constants.
static SDValue extractShiftForRotate(SelectionDAG &DAG, SDValue OppShift, SDValue ExtractFrom, SDValue &Mask, const SDLoc &DL)
Helper function for visitOR to extract the needed side of a rotate idiom from a shl/srl/mul/udiv.
static bool getCombineLoadStoreParts(SDNode *N, unsigned Inc, unsigned Dec, bool &IsLoad, bool &IsMasked, SDValue &Ptr, const TargetLowering &TLI)
bool refineUniformBase(SDValue &BasePtr, SDValue &Index, bool IndexIsScaled, SelectionDAG &DAG, const SDLoc &DL)
static SDValue 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 narrowInsertExtractVectorBinOp(SDNode *Extract, SelectionDAG &DAG, bool LegalOperations)
static SDValue combineCarryDiamond(SelectionDAG &DAG, const TargetLowering &TLI, SDValue N0, SDValue N1, SDNode *N)
static SDValue foldExtendVectorInregToExtendOfSubvector(SDNode *N, const SDLoc &DL, const TargetLowering &TLI, SelectionDAG &DAG, bool LegalOperations)
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 narrowExtractedVectorBinOp(SDNode *Extract, SelectionDAG &DAG, bool LegalOperations)
If we are extracting a subvector produced by a wide binary operator try to use a narrow binary operat...
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 getInputChainForNode(SDNode *N)
Given a node, return its input chain if it has one, otherwise return a null sd operand.
static SDValue narrowExtractedVectorLoad(SDNode *Extract, SelectionDAG &DAG)
If we are extracting a subvector from a wide vector load, convert to a narrow load to eliminate the e...
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 replaceShuffleOfInsert(ShuffleVectorSDNode *Shuf, SelectionDAG &DAG)
If a shuffle inserts exactly one element from a source vector operand into another vector operand and...
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 foldExtractSubvectorFromShuffleVector(SDNode *N, SelectionDAG &DAG, const TargetLowering &TLI, bool LegalOperations)
Given EXTRACT_SUBVECTOR(VECTOR_SHUFFLE(Op0, Op1, Mask)), try to produce VECTOR_SHUFFLE(EXTRACT_SUBVEC...
static SDValue combineConcatVectorOfExtracts(SDNode *N, SelectionDAG &DAG)
static bool hasNoInfs(const TargetOptions &Options, SDValue N)
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 std::pair< unsigned, unsigned > CheckForMaskedLoad(SDValue V, SDValue Ptr, SDValue Chain)
Check to see if V is (and load (ptr), imm), where the load is having specific bytes cleared out.
static int getShuffleMaskIndexOfOneElementFromOp0IntoOp1(ArrayRef< int > Mask)
If the shuffle mask is taking exactly one element from the first vector operand and passing through a...
static bool shouldConvertSelectOfConstantsToMath(const SDValue &Cond, EVT VT, const TargetLowering &TLI)
static cl::opt< bool > EnableStoreMerging("combiner-store-merging", cl::Hidden, cl::init(true), cl::desc("DAG combiner enable merging multiple stores " "into a wider store"))
static bool isContractableFMUL(const TargetOptions &Options, SDValue N)
static cl::opt< bool > MaySplitLoadIndex("combiner-split-load-index", cl::Hidden, cl::init(true), cl::desc("DAG combiner may split indexing from loads"))
static bool areSlicesNextToEachOther(const LoadedSlice &First, const LoadedSlice &Second)
Check whether or not First and Second are next to each other in memory.
static SDValue stripConstantMask(const SelectionDAG &DAG, SDValue Op, SDValue &Mask)
static bool arebothOperandsNotSNan(SDValue Operand1, SDValue Operand2, SelectionDAG &DAG)
static bool isBSwapHWordPair(SDValue N, MutableArrayRef< SDNode * > Parts)
static SDValue foldFPToIntToFP(SDNode *N, const SDLoc &DL, SelectionDAG &DAG, const TargetLowering &TLI)
static bool CanCombineFCOPYSIGN_EXTEND_ROUND(EVT XTy, EVT YTy)
copysign(x, fp_extend(y)) -> copysign(x, y) copysign(x, fp_round(y)) -> copysign(x,...
static cl::opt< bool > ReduceLoadOpStoreWidthForceNarrowingProfitable("combiner-reduce-load-op-store-width-force-narrowing-profitable", cl::Hidden, cl::init(false), cl::desc("DAG combiner force override the narrowing profitable check when " "reducing the width of load/op/store sequences"))
static unsigned getMinMaxOpcodeForFP(SDValue Operand1, SDValue Operand2, ISD::CondCode CC, unsigned OrAndOpcode, SelectionDAG &DAG, bool isFMAXNUMFMINNUM_IEEE, bool isFMAXNUMFMINNUM)
static SDValue getTruncatedUSUBSAT(EVT DstVT, EVT SrcVT, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
static SDValue foldToSaturated(SDNode *N, EVT &VT, SDValue &Src, EVT &SrcVT, SDLoc &DL, const TargetLowering &TLI, SelectionDAG &DAG)
static SDValue FoldIntToFPToInt(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
static SDValue foldSubCtlzNot(SDNode *N, SelectionDAG &DAG)
static SDNode * getPostIndexedLoadStoreOp(SDNode *N, bool &IsLoad, bool &IsMasked, SDValue &Ptr, SDValue &BasePtr, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG, const TargetLowering &TLI)
static SDValue extractBooleanFlip(SDValue V, SelectionDAG &DAG, const TargetLowering &TLI, bool Force)
Flips a boolean if it is cheaper to compute.
static bool isTruncateOf(SelectionDAG &DAG, SDValue N, SDValue &Op, KnownBits &Known)
static SDValue tryToFoldExtOfMaskedLoad(SelectionDAG &DAG, const TargetLowering &TLI, EVT VT, bool LegalOperations, SDNode *N, SDValue N0, ISD::LoadExtType ExtLoadType, ISD::NodeType ExtOpc)
static SDValue getSubVectorSrc(SDValue V, SDValue Index, EVT SubVT)
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 cl::opt< bool > EnableVectorFCopySignExtendRound("combiner-vector-fcopysign-extend-round", cl::Hidden, cl::init(false), cl::desc("Enable merging extends and rounds into FCOPYSIGN on vector types"))
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 bool matchRotateSub(SDValue Pos, SDValue Neg, unsigned EltSize, SelectionDAG &DAG, bool IsRotate)
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 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 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 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...
static bool isSlicingProfitable(SmallVectorImpl< LoadedSlice > &LoadedSlices, const APInt &UsedBits, bool ForCodeSize)
Check the profitability of all involved LoadedSlice.
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)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines the DenseMap class.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static bool isSigned(unsigned int Opcode)
static bool isUndef(ArrayRef< int > Mask)
static MaybeAlign getAlign(Value *Ptr)
iv Induction Variable Users
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.
unsigned const TargetRegisterInfo * TRI
This file provides utility analysis objects describing memory locations.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
const SmallVectorImpl< MachineOperand > & Cond
Contains matchers for matching SelectionDAG nodes and values.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)
This file describes how to lower LLVM code to machine code.
static constexpr int Concat[]
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
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
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 void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
Dual division/remainder interface.
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.
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.
APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
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.
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
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 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.
APInt smul_ov(const APInt &RHS, bool &Overflow) const
bool isMask(unsigned numBits) const
bool ule(const APInt &RHS) const
Unsigned less or equal comparison.
APInt sext(unsigned width) const
Sign extend to a new width.
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.
APInt extractBits(unsigned numBits, unsigned bitPosition) const
Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
bool isOne() const
Determine if this is a value of 1.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
size - Get the array size.
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
This is an SDNode representing atomic operations.
static BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
static 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)
A "pseudo-class" with methods for operating on BUILD_VECTORs.
Represents known origin of an individual byte in combine pattern.
static ByteProvider getConstantZero()
static ByteProvider getSrc(std::optional< ISelOp > Val, int64_t ByteOffset, int64_t VectorOffset)
static 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.
ConstantFP - Floating Point Values [float, double].
bool isMinSignedValue() const
const ConstantInt * getConstantIntValue() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
This is an important base class in LLVM.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
static bool shouldExecute(unsigned CounterName)
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const 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.
Helper struct to store a base, index and offset that forms an address.
This class is used to form a handle around another node that is persistent and is updated across invo...
This is an important class for using LLVM in a threaded context.
Base class for LoadSDNode and StoreSDNode.
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 auto all_valuetypes()
SimpleValueType Iteration.
static MVT getIntegerVT(unsigned BitWidth)
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.
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
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.
This class is used to represent an MGATHER node.
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,...
This class is used to represent an MSCATTER node.
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.
const MDNode * getRanges() const
Returns the Ranges that describes the dereference.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
Align getOriginalAlign() const
Returns alignment and volatility of the memory access.
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.
Representation for a specific memory location.
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.
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.
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.
void intersectFlagsWith(const SDNodeFlags Flags)
Clear any flags in this node that aren't also set in Flags.
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.
use_iterator use_begin() const
Provide iteration support to walk over all uses of an SDNode.
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.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
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()
bool hasNUsesOfValue(unsigned NUses, unsigned Value) const
Return true if there are exactly NUSES uses of the indicated value.
void setFlags(SDNodeFlags NewFlags)
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.
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...
virtual bool disableGenericCombines(CodeGenOptLevel OptLevel) const
Help to insert SDNodeFlags automatically in transforming.
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.
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 ...
SDValue getSplatSourceVector(SDValue V, int &SplatIndex)
If V is a splatted value, return the source vector and its splat index.
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.
SDValue getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, ISD::LoadExtType ExtTy)
bool isKnownNeverSNaN(SDValue Op, unsigned Depth=0) const
const TargetSubtargetInfo & getSubtarget() const
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
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...
SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, const SDLoc &dl)
Constant fold a setcc to true or false.
SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
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.
SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm, bool ConstantFold=true)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
SDValue getConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offs=0, bool isT=false, unsigned TargetFlags=0)
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...
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-...
void Combine(CombineLevel Level, BatchAAResults *BatchAA, CodeGenOptLevel OptLevel)
This iterates over the nodes in the SelectionDAG, folding certain types of nodes together,...
SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
static unsigned getHasPredecessorMaxSteps()
bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
bool cannotBeOrderedNegativeFP(SDValue Op) const
Test whether the given float value is known to be positive.
SDValue getGetFPEnv(SDValue Chain, const SDLoc &dl, SDValue Ptr, EVT MemVT, MachineMemOperand *MMO)
SDValue getAssertAlign(const SDLoc &DL, SDValue V, Align A)
Return an AssertAlignSDNode.
SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue 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.
SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO)
Gets a node for an atomic op, produces result (if relevant) and chain and takes 2 operands.
bool shouldOptForSize() const
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
SDValue getIndexedMaskedLoad(SDValue OrigLoad, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM)
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.
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...
void salvageDebugInfo(SDNode &N)
To be invoked on an SDNode that is slated to be erased.
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
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.
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.
void DeleteNode(SDNode *N)
Remove the specified node from the system.
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...
SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
SDValue simplifySelect(SDValue Cond, SDValue TVal, SDValue FVal)
Try to simplify a select/vselect into 1 of its operands or a constant.
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.
bool isConstantFPBuildVectorOrConstantFP(SDValue N) const
Test whether the given value is a constant FP or similar node.
const DataLayout & getDataLayout() const
SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl< SDValue > &Vals)
Creates a new TokenFactor containing Vals.
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 ...
bool doesNodeExist(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops)
Check if a node exists without modifying its flags.
bool areNonVolatileConsecutiveLoads(LoadSDNode *LD, LoadSDNode *Base, unsigned Bytes, int Dist) const
Return true if loads are next to each other and can be merged.
SDValue getMaskedHistogram(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
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)
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
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.
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())
void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
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,...
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.
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)
MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
void RemoveDeadNodes()
This method deletes all unreachable nodes in the SelectionDAG.
bool isConstantValueOfAnyType(SDValue N) const
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...
bool isKnownToBeAPowerOfTwo(SDValue Val, unsigned Depth=0) const
Test if the given value is known to have exactly one bit set.
bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
SDValue getIndexedStore(SDValue OrigStore, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM)
SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
SDValue getSetFPEnv(SDValue Chain, const SDLoc &dl, SDValue Ptr, EVT MemVT, MachineMemOperand *MMO)
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 ...
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
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()
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond)
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
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)
SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
SDValue getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getValueType(EVT)
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
bool isKnownNeverNaN(SDValue Op, 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.
SDValue getIndexedMaskedStore(SDValue OrigStore, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM)
const TargetLibraryInfo & getLibInfo() const
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.
bool MaskedVectorIsZero(SDValue Op, const APInt &DemandedElts, unsigned Depth=0) const
Return true if 'Op' is known to be zero in DemandedElts.
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.
SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
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
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.
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.
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.
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...
bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
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.
std::optional< uint64_t > 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...
LLVMContext * getContext() const
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.
bool isUndef(unsigned Opcode, ArrayRef< SDValue > Ops)
Return true if the result of this operation is always undefined.
SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags)
Get the specified node if it's already available, or else return NULL.
std::optional< bool > isBoolConstant(SDValue N, bool AllowTruncation=false) const
Check if a value \op N is a constant using the target's BooleanContent for its type.
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.
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.
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...
SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
SDValue simplifyShift(SDValue X, SDValue Y)
Try to simplify a shift into 1 of its operands or a constant.
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 ...
SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
SDValue getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, bool IsTruncating=false)
A vector that has set insertion semantics.
bool remove(const value_type &X)
Remove an item from the set vector.
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 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.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
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)
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.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual bool canCombineTruncStore(EVT ValVT, EVT MemVT, bool LegalOnly) const
virtual bool convertSetCCLogicToBitwiseLogic(EVT VT) const
Use bitwise logic to make pairs of compares more efficient.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual bool isVectorLoadExtDesirable(SDValue ExtVal) const
Return true if folding a vector load into ExtVal (a sign, zero, or any extend node) is profitable.
int getRecipEstimateSqrtEnabled(EVT VT, MachineFunction &MF) const
Return a ReciprocalEstimate enum value for a square root of the given type based on the function's at...
virtual bool isSExtCheaperThanZExt(EVT FromTy, EVT ToTy) const
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
virtual MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual bool isFPExtFoldable(const MachineInstr &MI, unsigned Opcode, LLT DestTy, LLT SrcTy) const
Return true if an fpext operation input to an Opcode operation is free (for instance,...
virtual bool hasBitTest(SDValue X, SDValue Y) const
Return true if the target has a bit-test instruction: (X & (1 << Y)) ==/!= 0 This knowledge can be us...
bool isTruncStoreLegal(EVT ValVT, EVT MemVT) const
Return true if the specified store with truncation is legal on this target.
virtual bool isLoadBitCastBeneficial(EVT LoadVT, EVT BitcastVT, const SelectionDAG &DAG, const MachineMemOperand &MMO) const
Return true if the following transform is beneficial: fold (conv (load x)) -> (load (conv*)x) On arch...
virtual bool areTwoSDNodeTargetMMOFlagsMergeable(const MemSDNode &NodeX, const MemSDNode &NodeY) const
Return true if it is valid to merge the TargetMMOFlags in two SDNodes.
virtual bool isCommutativeBinOp(unsigned Opcode) const
Returns true if the opcode is a commutative binary operation.
virtual bool isFPImmLegal(const APFloat &, EVT, bool ForCodeSize=false) const
Returns true if the target can instruction select the specified FP immediate natively.
virtual bool isExtractVecEltCheap(EVT VT, unsigned Index) const
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
virtual bool optimizeFMulOrFDivAsShiftAddBitcast(SDNode *N, SDValue FPConst, SDValue IntPow2) const
virtual bool shouldNormalizeToSelectSequence(LLVMContext &Context, EVT VT) const
Returns true if we should normalize select(N0&N1, X, Y) => select(N0, select(N1, X,...
virtual bool preferScalarizeSplat(SDNode *N) const
bool isIndexedMaskedLoadLegal(unsigned IdxMode, EVT VT) const
Return true if the specified indexed load is legal on this target.
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,...
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 shouldFoldConstantShiftPairToMask(const SDNode *N, CombineLevel Level) const
Return true if it is profitable to fold a pair of shifts into a mask.
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 shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT) const
Return true if pulling a binary operation into a select with an identity constant is profitable.
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.
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 shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT) const
Return true if it is profitable to reduce a load to a smaller type.
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...
@ 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...
virtual bool mergeStoresAfterLegalization(EVT MemVT) const
Allow store merging for the specified type after legalization in addition to before legalization.
virtual bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
Return true if the target supports a memory access of this type for the given address space and align...
unsigned getGatherAllAliasesMaxDepth() const
virtual bool storeOfVectorConstantIsCheap(bool IsZero, EVT MemVT, unsigned NumElem, unsigned AddrSpace) const
Return true if it is expected to be cheaper to do a store of vector constant with the given size and ...
virtual bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
virtual bool isMultiStoresCheaperThanBitsMerge(EVT LTy, EVT HTy) const
Return true if it is cheaper to split the store of a merged int val from a pair of smaller values int...
bool isLoadExtLegalOrCustom(unsigned ExtType, EVT ValVT, EVT MemVT) const
Return true if the specified load with extension is legal or custom on this target.
bool isAtomicLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const
Return true if the specified atomic load with extension is legal on this target.
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
virtual bool shouldFoldMaskToVariableShiftPair(SDValue X) const
There are two ways to clear extreme bits (either low or high): Mask: x & (-1 << y) (the instcombine c...
bool isIndexedLoadLegal(unsigned IdxMode, EVT VT) const
Return true if the specified indexed load is legal on this target.
virtual bool canMergeStoresTo(unsigned AS, EVT MemVT, const MachineFunction &MF) const
Returns if it's reasonable to merge stores to MemVT size.
virtual bool preferABDSToABSWithNSW(EVT VT) const
bool isLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const
Return true if the specified load with extension is legal on this target.
AndOrSETCCFoldKind
Enum of different potentially desirable ways to fold (and/or (setcc ...), (setcc ....
virtual bool shouldScalarizeBinop(SDValue VecOp) const
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
virtual bool isStoreBitCastBeneficial(EVT StoreVT, EVT BitcastVT, const SelectionDAG &DAG, const MachineMemOperand &MMO) const
Return true if the following transform is beneficial: (store (y (conv x)), y*)) -> (store x,...
bool isIndexedMaskedStoreLegal(unsigned IdxMode, EVT VT) const
Return true if the specified indexed load is legal on this target.
virtual bool isVectorClearMaskLegal(ArrayRef< int >, EVT) const
Similar to isShuffleMaskLegal.
bool hasTargetDAGCombine(ISD::NodeType NT) const
If true, the target has custom DAG combine transformations that it can perform for the specified node...
virtual bool shouldSplatInsEltVarIndex(EVT) const
Return true if inserting a scalar into a variable element of an undef vector is more efficiently hand...
NegatibleCost
Enum that specifies when a float negation is beneficial.
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
int getSqrtRefinementSteps(EVT VT, MachineFunction &MF) const
Return the refinement step count for a square root of the given type based on the function's attribut...
virtual unsigned preferedOpcodeForCmpEqPiecesOfOperand(EVT VT, unsigned ShiftOpc, bool MayTransformRotate, const APInt &ShiftOrRotateAmt, const std::optional< APInt > &AndMask) const
virtual bool isFMADLegal(const MachineInstr &MI, LLT Ty) const
Returns true if MI can be combined with another instruction to form TargetOpcode::G_FMAD.
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
virtual bool aggressivelyPreferBuildVectorSources(EVT VecVT) const
virtual bool shouldRemoveExtendFromGSIndex(SDValue Extend, EVT DataVT) const
virtual bool isFAbsFree(EVT VT) const
Return true if an fabs operation is free to the point where it is never worthwhile to replace it with...
LegalizeAction getOperationAction(unsigned Op, EVT VT) const
Return how this operation should be treated: either it is legal, needs to be promoted to a larger siz...
virtual bool generateFMAsInMachineCombiner(EVT VT, CodeGenOptLevel OptLevel) const
virtual bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AddrSpace, Instruction *I=nullptr) const
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
virtual bool hasPairedLoad(EVT, Align &) const
Return true if the target supplies and combines to a paired load two loaded values of type LoadedType...
virtual bool convertSelectOfConstantsToMath(EVT VT) const
Return true if a select of constants (select Cond, C1, C2) should be transformed into simple math ops...
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
virtual SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const
Hooks for building estimates in place of slower divisions and square roots.
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
virtual bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, SDValue N1) const
SDValue getCheaperOrNeutralNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, const NegatibleCost CostThreshold=NegatibleCost::Neutral, unsigned Depth=0) const
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 "look through" ops that don't contri...
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.
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().
SDValue getVectorElementPointer(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 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...
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...
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.
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 UnsafeFPMath
UnsafeFPMath - This flag is enabled when the -enable-unsafe-fp-math flag is specified on the command ...
unsigned NoSignedZerosFPMath
NoSignedZerosFPMath - This flag is enabled when the -enable-no-signed-zeros-fp-math is specified on t...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual bool useAA() const
Enable use of alias analysis during code generation (during MI scheduling, DAGCombine,...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
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.
unsigned getOperandNo() const
Return the operand # of this use in its User.
Value * getOperand(unsigned i) const
This class is used to represent an VP_GATHER node.
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
This class is used to represent an VP_SCATTER node.
const SDValue & getValue() const
This class is used to represent EVT's, which are used to parameterize some operations.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
user_iterator user_begin()
bool hasOneUse() const
Return true if there is exactly one use of this value.
iterator_range< user_iterator > users()
iterator_range< use_iterator > uses()
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.
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.
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...
bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ 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...
@ 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.
@ 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 or maximum on two values.
@ 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
@ 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)
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 matchUnaryPredicate(SDValue Op, std::function< bool(ConstantSDNode *)> Match, bool AllowUndefs=false)
Hook for matching ConstantSDNode predicate.
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)
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...
bool isVPBinaryOp(unsigned Opcode)
Whether this is a vector-predicated binary operation opcode.
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.
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.
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.
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...
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...
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...
bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
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,...
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...
bool isVPReduction(unsigned Opcode)
Whether this is a vector-predicated reduction opcode.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
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,...
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).
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< 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::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.
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()...
BinaryOp_match< cst_pred_ty< is_zero_int >, ValTy, Instruction::Sub > m_Neg(const ValTy &V)
Matches a 'Neg' as 'sub 0, V'.
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< cst_pred_ty< is_all_ones >, ValTy, Instruction::Xor, true > m_Not(const ValTy &V)
Matches a 'Not' as 'xor V, -1' or 'xor -1, V'.
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.
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)
Libcall
RTLIB::Libcall enum - This enum defines all of the runtime library calls the backend can emit.
@ Undef
Value of the register doesn't matter.
Opcode_match m_Opc(unsigned Opcode)
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_UMaxLike(const LHS &L, const RHS &R)
Or< Preds... > m_AnyOf(const Preds &...preds)
And< Preds... > m_AllOf(const Preds &...preds)
TernaryOpc_match< T0_P, T1_P, T2_P > m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC)
UnaryOpc_match< Opnd > m_AnyExt(const Opnd &Op)
auto m_SMaxLike(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_Ctlz(const Opnd &Op)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
UnaryOpc_match< Opnd > m_UnaryOp(unsigned Opc, const Opnd &Op)
auto m_SMinLike(const LHS &L, const RHS &R)
CondCode_match m_SpecificCondCode(ISD::CondCode CC)
Match a conditional code SDNode with a specific ISD::CondCode.
NUses_match< 1, Value_match > m_OneUse()
CondCode_match m_CondCode()
Match any conditional code SDNode.
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 interger constants or splat of an integer constant.
initializer< Ty > init(const Ty &Val)
int ilogb(const IEEEFloat &Arg)
DiagnosticInfoOptimizationBase::Argument NV
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)
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.
int popcount(T Value) noexcept
Count the number of set bits in a value.
bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
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...
SDValue getBitwiseNotOperand(SDValue V, SDValue Mask, bool AllowUndefs)
If V is a bitwise not, returns the inverted operand.
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,...
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::SmallVector< int, 16 > createUnaryMask(ArrayRef< int > Mask, unsigned NumElts)
Given a shuffle mask for a binary shuffle, create the equivalent shuffle mask assuming both operands ...
bool isIntOrFPConstant(SDValue V)
Return true if V is either a integer or FP constant.
bool operator!=(uint64_t V1, const APInt &V2)
bool operator>=(int64_t V1, const APSInt &V2)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt & operator+=(DynamicAPInt &A, int64_t B)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
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...
Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
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)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
bool isMinSignedConstant(SDValue V)
Returns true if V is a constant min signed integer value.
ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
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)
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.
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)
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)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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.
SDValue peekThroughOneUseBitcasts(SDValue V)
Return the non-bitcasted and one-use source operand of V if it exists.
CodeGenOptLevel
Code generation optimization level.
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.
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...
@ 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.
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
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...
bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
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.
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.
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)
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.
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.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
AAMDNodes concat(const AAMDNodes &Other) const
Determine the best AAMDNodes after concatenating two different locations together.
static ExponentType semanticsMinExponent(const fltSemantics &)
static constexpr roundingMode rmNearestTiesToEven
static ExponentType semanticsMaxExponent(const fltSemantics &)
static unsigned int semanticsPrecision(const fltSemantics &)
opStatus
IEEE-754R 7: Default exception handling.
static unsigned int semanticsIntSizeInBits(const fltSemantics &, bool)
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
Represent subnormal handling kind for floating point instruction inputs and outputs.
static constexpr DenormalMode getIEEE()
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool knownBitsLE(EVT VT) const
Return true if we know at compile time this has fewer than or the same bits as VT.
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
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
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.
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.
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,...
unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
static MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoUnsignedWrap() const
bool hasNoSignedWrap() const
bool hasAllowReassociation() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
Clients of various APIs that cause global effects on the DAG can optionally implement this interface.
virtual void NodeDeleted(SDNode *N, SDNode *E)
The node N that was deleted and, if E is not null, an equivalent node E that replaced it.
virtual void NodeInserted(SDNode *N)
The node N that was inserted.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
void AddToWorklist(SDNode *N)
bool recursivelyDeleteUnusedNodes(SDNode *N)
SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
void CommitTargetLoweringOpt(const TargetLoweringOpt &TLO)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...