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), AA(AA) {
256 MaximumLegalStoreInBits = 0;
262 VT.getSizeInBits().getKnownMinValue() >= MaximumLegalStoreInBits)
263 MaximumLegalStoreInBits = VT.getSizeInBits().getKnownMinValue();
266 void ConsiderForPruning(
SDNode *
N) {
273 void AddToWorklist(
SDNode *
N,
bool IsCandidateForPruning =
true,
274 bool SkipIfCombinedBefore =
false) {
276 "Deleted Node added to Worklist");
283 if (SkipIfCombinedBefore &&
N->getCombinerWorklistIndex() == -2)
286 if (IsCandidateForPruning)
287 ConsiderForPruning(
N);
289 if (
N->getCombinerWorklistIndex() < 0) {
290 N->setCombinerWorklistIndex(Worklist.
size());
296 void removeFromWorklist(
SDNode *
N) {
298 StoreRootCountMap.
erase(
N);
300 int WorklistIndex =
N->getCombinerWorklistIndex();
304 if (WorklistIndex < 0)
308 Worklist[WorklistIndex] =
nullptr;
309 N->setCombinerWorklistIndex(-1);
312 void deleteAndRecombine(
SDNode *
N);
313 bool recursivelyDeleteUnusedNodes(
SDNode *
N);
321 return CombineTo(
N, &Res, 1, AddTo);
328 return CombineTo(
N, To, 2, AddTo);
334 unsigned MaximumLegalStoreInBits;
340 unsigned BitWidth =
Op.getScalarValueSizeInBits();
346 EVT VT =
Op.getValueType();
350 return SimplifyDemandedBits(
Op,
DemandedBits, DemandedElts,
false);
356 bool SimplifyDemandedVectorElts(
SDValue Op) {
358 if (
Op.getValueType().isScalableVector())
361 unsigned NumElts =
Op.getValueType().getVectorNumElements();
363 return SimplifyDemandedVectorElts(
Op, DemandedElts);
367 const APInt &DemandedElts,
368 bool AssumeSingleUse =
false);
369 bool SimplifyDemandedVectorElts(
SDValue Op,
const APInt &DemandedElts,
370 bool AssumeSingleUse =
false);
372 bool CombineToPreIndexedLoadStore(
SDNode *
N);
373 bool CombineToPostIndexedLoadStore(
SDNode *
N);
398 void ReplaceLoadWithPromotedLoad(
SDNode *Load,
SDNode *ExtLoad);
539 bool refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
SDNode *
N);
571 template <
class MatchContextClass>
573 template <
class MatchContextClass>
578 bool reassociationCanBreakAddressingModePattern(
unsigned Opc,
587 SDValue reassociateReduction(
unsigned RedOpc,
unsigned Opc,
const SDLoc &
DL,
601 bool NotExtCompare =
false);
602 SDValue convertSelectOfFPConstantsToLoadOffset(
619 const SDLoc &
DL,
bool foldBooleans);
623 SDValue &
CC,
bool MatchStrict =
false)
const;
624 bool isOneUseSetCC(
SDValue N)
const;
649 bool KnownNeverZero =
false,
650 bool InexpensiveOnly =
false,
651 std::optional<EVT> OutVT = std::nullopt);
661 bool DemandHighBits =
true);
665 unsigned PosOpcode,
unsigned NegOpcode,
669 unsigned PosOpcode,
unsigned NegOpcode,
685 SDValue VecIn2,
unsigned LeftIdx,
720 int64_t OffsetFromBase;
723 : MemNode(
N), OffsetFromBase(
Offset) {}
728 StoreSource getStoreSource(
SDValue StoreVal) {
732 return StoreSource::Constant;
736 return StoreSource::Constant;
737 return StoreSource::Unknown;
740 return StoreSource::Extract;
742 return StoreSource::Load;
744 return StoreSource::Unknown;
752 bool isMulAddWithConstProfitable(
SDNode *MulNode,
SDValue AddNode,
759 EVT LoadResultTy,
EVT &ExtVT);
764 EVT &MemVT,
unsigned ShAmt = 0);
772 bool BackwardsPropagateMask(
SDNode *
N);
789 EVT MemVT,
unsigned NumStores,
790 bool IsConstantSrc,
bool UseVector,
803 bool checkMergeStoreCandidatesForDependencies(
811 int64_t ElementSizeBytes)
const;
816 unsigned NumConsecutiveStores,
817 EVT MemVT,
SDNode *Root,
bool AllowVectors);
824 unsigned NumConsecutiveStores,
EVT MemVT,
830 unsigned NumConsecutiveStores,
EVT MemVT,
831 SDNode *Root,
bool AllowVectors,
832 bool IsNonTemporalStore,
bool IsNonTemporalLoad);
851 bool hasOperation(
unsigned Opcode,
EVT VT) {
862 EVT getShiftAmountTy(
EVT LHSTy) {
868 bool isTypeLegal(
const EVT &VT) {
869 if (!LegalTypes)
return true;
874 EVT getSetCCResultType(
EVT VT)
const {
889 explicit WorklistRemover(DAGCombiner &dc)
890 :
SelectionDAG::DAGUpdateListener(dc.getDAG()), DC(dc) {}
893 DC.removeFromWorklist(
N);
901 explicit WorklistInserter(DAGCombiner &dc)
902 :
SelectionDAG::DAGUpdateListener(dc.getDAG()), DC(dc) {}
916 ((DAGCombiner*)
DC)->AddToWorklist(
N);
921 return ((DAGCombiner*)DC)->CombineTo(
N, &To[0], To.
size(), AddTo);
926 return ((DAGCombiner*)DC)->CombineTo(
N, Res, AddTo);
931 return ((DAGCombiner*)DC)->CombineTo(
N, Res0, Res1, AddTo);
936 return ((DAGCombiner*)DC)->recursivelyDeleteUnusedNodes(
N);
941 return ((DAGCombiner*)DC)->CommitTargetLoweringOpt(TLO);
948void DAGCombiner::deleteAndRecombine(
SDNode *
N) {
949 removeFromWorklist(
N);
957 if (
Op->hasOneUse() ||
Op->getNumValues() > 1)
958 AddToWorklist(
Op.getNode());
967 unsigned Bits =
Offset + std::max(
LHS.getBitWidth(),
RHS.getBitWidth());
980 LHS =
N.getOperand(0);
981 RHS =
N.getOperand(1);
982 CC =
N.getOperand(2);
989 LHS =
N.getOperand(1);
990 RHS =
N.getOperand(2);
991 CC =
N.getOperand(3);
1003 LHS =
N.getOperand(0);
1004 RHS =
N.getOperand(1);
1005 CC =
N.getOperand(4);
1012bool DAGCombiner::isOneUseSetCC(
SDValue N)
const {
1014 if (isSetCCEquivalent(
N, N0, N1, N2) &&
N->hasOneUse())
1026 MaskForTy = 0xFFULL;
1029 MaskForTy = 0xFFFFULL;
1032 MaskForTy = 0xFFFFFFFFULL;
1051 return !(Const->isOpaque() && NoOpaques);
1054 unsigned BitWidth =
N.getScalarValueSizeInBits();
1059 if (!Const || Const->getAPIntValue().getBitWidth() !=
BitWidth ||
1060 (Const->isOpaque() && NoOpaques))
1079 !cast<ConstantSDNode>(LD->getOperand(2))->isOpaque());
1082bool DAGCombiner::reassociationCanBreakAddressingModePattern(
unsigned Opc,
1115 ScalableOffset = -ScalableOffset;
1117 if (
auto *LoadStore = dyn_cast<MemSDNode>(
Node);
1123 unsigned AS =
LoadStore->getAddressSpace();
1136 auto *C2 = dyn_cast<ConstantSDNode>(N1);
1140 const APInt &C2APIntVal = C2->getAPIntValue();
1144 if (
auto *C1 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) {
1148 const APInt &C1APIntVal = C1->getAPIntValue();
1149 const APInt CombinedValueIntVal = C1APIntVal + C2APIntVal;
1152 const int64_t CombinedValue = CombinedValueIntVal.
getSExtValue();
1155 if (
auto *LoadStore = dyn_cast<MemSDNode>(
Node)) {
1161 AM.
BaseOffs = C2APIntVal.getSExtValue();
1163 unsigned AS =
LoadStore->getAddressSpace();
1175 if (
auto *GA = dyn_cast<GlobalAddressSDNode>(N0.
getOperand(1)))
1188 AM.
BaseOffs = C2APIntVal.getSExtValue();
1190 unsigned AS =
LoadStore->getAddressSpace();
1203SDValue DAGCombiner::reassociateOpsCommutative(
unsigned Opc,
const SDLoc &
DL,
1217 Flags.hasNoUnsignedWrap())
1225 return DAG.
getNode(Opc,
DL, VT, N00, OpNode, NewFlags);
1233 return DAG.
getNode(Opc,
DL, VT, OpNode, N01, NewFlags);
1243 if (N1 == N00 || N1 == N01)
1289 if (CC1 == CC00 && CC1 != CC01) {
1291 return DAG.
getNode(Opc,
DL, VT, OpNode, N01, Flags);
1293 if (CC1 == CC01 && CC1 != CC00) {
1295 return DAG.
getNode(Opc,
DL, VT, OpNode, N00, Flags);
1313 if (!
Flags.hasAllowReassociation() || !
Flags.hasNoSignedZeros())
1316 if (
SDValue Combined = reassociateOpsCommutative(Opc,
DL, N0, N1, Flags))
1318 if (
SDValue Combined = reassociateOpsCommutative(Opc,
DL, N1, N0, Flags))
1326SDValue DAGCombiner::reassociateReduction(
unsigned RedOpc,
unsigned Opc,
1344 assert(
N->getNumValues() == NumTo &&
"Broken CombineTo call!");
1348 dbgs() <<
" and " << NumTo - 1 <<
" other values\n");
1349 for (
unsigned i = 0, e = NumTo; i !=
e; ++i)
1351 N->getValueType(i) == To[i].getValueType()) &&
1352 "Cannot combine value to value of different type!");
1354 WorklistRemover DeadNodes(*
this);
1358 for (
unsigned i = 0, e = NumTo; i !=
e; ++i) {
1360 AddToWorklistWithUsers(To[i].
getNode());
1368 deleteAndRecombine(
N);
1386 recursivelyDeleteUnusedNodes(TLO.
Old.
getNode());
1392 const APInt &DemandedElts,
1393 bool AssumeSingleUse) {
1401 AddToWorklist(
Op.getNode());
1403 CommitTargetLoweringOpt(TLO);
1410bool DAGCombiner::SimplifyDemandedVectorElts(
SDValue Op,
1411 const APInt &DemandedElts,
1412 bool AssumeSingleUse) {
1414 APInt KnownUndef, KnownZero;
1416 TLO, 0, AssumeSingleUse))
1420 AddToWorklist(
Op.getNode());
1422 CommitTargetLoweringOpt(TLO);
1426void DAGCombiner::ReplaceLoadWithPromotedLoad(
SDNode *Load,
SDNode *ExtLoad) {
1428 EVT VT =
Load->getValueType(0);
1437 AddToWorklist(Trunc.
getNode());
1438 recursivelyDeleteUnusedNodes(Load);
1446 EVT MemVT =
LD->getMemoryVT();
1448 :
LD->getExtensionType();
1451 LD->getChain(),
LD->getBasePtr(),
1452 MemVT,
LD->getMemOperand());
1455 unsigned Opc =
Op.getOpcode();
1459 if (
SDValue Op0 = SExtPromoteOperand(
Op.getOperand(0), PVT))
1463 if (
SDValue Op0 = ZExtPromoteOperand(
Op.getOperand(0), PVT))
1481 EVT OldVT =
Op.getValueType();
1483 bool Replace =
false;
1484 SDValue NewOp = PromoteOperand(
Op, PVT, Replace);
1487 AddToWorklist(NewOp.
getNode());
1490 ReplaceLoadWithPromotedLoad(
Op.getNode(), NewOp.
getNode());
1496 EVT OldVT =
Op.getValueType();
1498 bool Replace =
false;
1499 SDValue NewOp = PromoteOperand(
Op, PVT, Replace);
1502 AddToWorklist(NewOp.
getNode());
1505 ReplaceLoadWithPromotedLoad(
Op.getNode(), NewOp.
getNode());
1513 if (!LegalOperations)
1516 EVT VT =
Op.getValueType();
1522 unsigned Opc =
Op.getOpcode();
1530 assert(PVT != VT &&
"Don't know what type to promote to!");
1534 bool Replace0 =
false;
1536 SDValue NN0 = PromoteOperand(N0, PVT, Replace0);
1538 bool Replace1 =
false;
1540 SDValue NN1 = PromoteOperand(N1, PVT, Replace1);
1552 Replace1 &= (N0 != N1) && !N1->
hasOneUse();
1555 CombineTo(
Op.getNode(), RV);
1581 if (!LegalOperations)
1584 EVT VT =
Op.getValueType();
1590 unsigned Opc =
Op.getOpcode();
1598 assert(PVT != VT &&
"Don't know what type to promote to!");
1602 bool Replace =
false;
1605 N0 = SExtPromoteOperand(N0, PVT);
1607 N0 = ZExtPromoteOperand(N0, PVT);
1609 N0 = PromoteOperand(N0, PVT, Replace);
1620 ReplaceLoadWithPromotedLoad(
Op.getOperand(0).getNode(), N0.
getNode());
1630 if (!LegalOperations)
1633 EVT VT =
Op.getValueType();
1639 unsigned Opc =
Op.getOpcode();
1647 assert(PVT != VT &&
"Don't know what type to promote to!");
1657bool DAGCombiner::PromoteLoad(
SDValue Op) {
1658 if (!LegalOperations)
1664 EVT VT =
Op.getValueType();
1670 unsigned Opc =
Op.getOpcode();
1678 assert(PVT != VT &&
"Don't know what type to promote to!");
1683 EVT MemVT =
LD->getMemoryVT();
1685 :
LD->getExtensionType();
1687 LD->getChain(),
LD->getBasePtr(),
1688 MemVT,
LD->getMemOperand());
1697 AddToWorklist(
Result.getNode());
1698 recursivelyDeleteUnusedNodes(
N);
1711bool DAGCombiner::recursivelyDeleteUnusedNodes(
SDNode *
N) {
1712 if (!
N->use_empty())
1722 if (
N->use_empty()) {
1723 for (
const SDValue &ChildN :
N->op_values())
1724 Nodes.
insert(ChildN.getNode());
1726 removeFromWorklist(
N);
1731 }
while (!Nodes.
empty());
1746 WorklistInserter AddNodes(*
this);
1755 AddToWorklist(&
Node,
Node.use_empty());
1763 while (
SDNode *
N = getNextWorklistEntry()) {
1767 if (recursivelyDeleteUnusedNodes(
N))
1770 WorklistRemover DeadNodes(*
this);
1778 for (
SDNode *LN : UpdatedNodes)
1779 AddToWorklistWithUsers(LN);
1791 for (
const SDValue &ChildN :
N->op_values())
1792 AddToWorklist(ChildN.getNode(),
true,
1803 ChainsWithoutMergeableStores.
clear();
1814 "Node was deleted but visit returned new node!");
1822 N->getNumValues() == 1 &&
"Type mismatch");
1832 AddToWorklistWithUsers(RV.
getNode());
1838 recursivelyDeleteUnusedNodes(
N);
1848 switch (
N->getOpcode()) {
1874 case ISD::MUL:
return visitMUL<EmptyMatchContext>(
N);
1938 case ISD::FMA:
return visitFMA<EmptyMatchContext>(
N);
2010#define BEGIN_REGISTER_VP_SDNODE(SDOPC, ...) case ISD::SDOPC:
2011#include "llvm/IR/VPIntrinsics.def"
2012 return visitVPOp(
N);
2023 if (!DisableGenericCombines)
2029 "Node was deleted but visit returned NULL!");
2036 DagCombineInfo(DAG, Level,
false,
this);
2044 switch (
N->getOpcode()) {
2052 RV = PromoteIntBinOp(
SDValue(
N, 0));
2057 RV = PromoteIntShiftOp(
SDValue(
N, 0));
2078 if (N0 != N1 && (isa<ConstantSDNode>(N0) || !isa<ConstantSDNode>(N1))) {
2093 if (
unsigned NumOps =
N->getNumOperands()) {
2094 if (
N->getOperand(0).getValueType() == MVT::Other)
2095 return N->getOperand(0);
2096 if (
N->getOperand(NumOps-1).getValueType() == MVT::Other)
2097 return N->getOperand(NumOps-1);
2098 for (
unsigned i = 1; i < NumOps-1; ++i)
2099 if (
N->getOperand(i).getValueType() == MVT::Other)
2100 return N->getOperand(i);
2106 SDValue Operand =
N->getOperand(0);
2121 if (
N->getNumOperands() == 2) {
2123 return N->getOperand(0);
2125 return N->getOperand(1);
2140 AddToWorklist(*(
N->user_begin()));
2145 bool Changed =
false;
2152 for (
unsigned i = 0; i < TFs.
size(); ++i) {
2157 for (
unsigned j = i;
j < TFs.
size();
j++)
2168 switch (
Op.getOpcode()) {
2186 if (SeenOps.
insert(
Op.getNode()).second)
2197 for (
unsigned i = 1, e = TFs.
size(); i < e; i++)
2198 AddToWorklist(TFs[i]);
2210 bool DidPruneOps =
false;
2212 unsigned NumLeftToConsider = 0;
2214 Worklist.
push_back(std::make_pair(
Op.getNode(), NumLeftToConsider++));
2218 auto AddToWorklist = [&](
unsigned CurIdx,
SDNode *
Op,
unsigned OpNumber) {
2224 unsigned OrigOpNumber = 0;
2225 while (OrigOpNumber < Ops.size() && Ops[OrigOpNumber].getNode() !=
Op)
2227 assert((OrigOpNumber != Ops.size()) &&
2228 "expected to find TokenFactor Operand");
2230 for (
unsigned i = CurIdx + 1; i < Worklist.
size(); ++i) {
2231 if (Worklist[i].second == OrigOpNumber) {
2232 Worklist[i].second = OpNumber;
2235 OpWorkCount[OpNumber] += OpWorkCount[OrigOpNumber];
2236 OpWorkCount[OrigOpNumber] = 0;
2237 NumLeftToConsider--;
2240 if (SeenChains.
insert(
Op).second) {
2241 OpWorkCount[OpNumber]++;
2246 for (
unsigned i = 0; i < Worklist.
size() && i < 1024; ++i) {
2248 if (NumLeftToConsider <= 1)
2250 auto CurNode = Worklist[i].first;
2251 auto CurOpNumber = Worklist[i].second;
2252 assert((OpWorkCount[CurOpNumber] > 0) &&
2253 "Node should not appear in worklist");
2254 switch (CurNode->getOpcode()) {
2260 NumLeftToConsider++;
2263 for (
const SDValue &
Op : CurNode->op_values())
2264 AddToWorklist(i,
Op.getNode(), CurOpNumber);
2270 AddToWorklist(i, CurNode->getOperand(0).getNode(), CurOpNumber);
2273 if (
auto *MemNode = dyn_cast<MemSDNode>(CurNode))
2274 AddToWorklist(i, MemNode->getChain().getNode(), CurOpNumber);
2277 OpWorkCount[CurOpNumber]--;
2278 if (OpWorkCount[CurOpNumber] == 0)
2279 NumLeftToConsider--;
2293 if (SeenChains.
count(
Op.getNode()) == 0)
2308 WorklistRemover DeadNodes(*
this);
2314 AddUsersToWorklist(
N);
2319 }
while (!
N->use_empty());
2320 deleteAndRecombine(
N);
2328 return Const !=
nullptr && !Const->isOpaque() ? Const :
nullptr;
2338 Op =
N->getOperand(0);
2340 if (
N->getFlags().hasNoUnsignedWrap())
2345 if (
N.getValueType().getScalarType() != MVT::i1 ||
2362 if (LD->isIndexed() || LD->getBasePtr().getNode() !=
N)
2364 VT = LD->getMemoryVT();
2365 AS = LD->getAddressSpace();
2367 if (ST->isIndexed() || ST->getBasePtr().getNode() !=
N)
2369 VT = ST->getMemoryVT();
2370 AS = ST->getAddressSpace();
2372 if (LD->isIndexed() || LD->getBasePtr().getNode() !=
N)
2374 VT = LD->getMemoryVT();
2375 AS = LD->getAddressSpace();
2377 if (ST->isIndexed() || ST->getBasePtr().getNode() !=
N)
2379 VT = ST->getMemoryVT();
2380 AS = ST->getAddressSpace();
2395 }
else if (
N->getOpcode() ==
ISD::SUB) {
2417 bool ShouldCommuteOperands) {
2422 if (ShouldCommuteOperands)
2434 unsigned Opcode =
N->getOpcode();
2435 EVT VT =
N->getValueType(0);
2442 unsigned OpNo = ShouldCommuteOperands ? 0 : 1;
2460 "Unexpected binary operator");
2477 unsigned SelOpNo = 0;
2513 bool CanFoldNonConst =
2519 if (!CanFoldNonConst &&
2527 if (CanFoldNonConst) {
2564 "Expecting add or sub");
2569 bool IsAdd =
N->getOpcode() ==
ISD::ADD;
2570 SDValue C = IsAdd ?
N->getOperand(1) :
N->getOperand(0);
2571 SDValue Z = IsAdd ?
N->getOperand(0) :
N->getOperand(1);
2572 auto *CN = dyn_cast<ConstantSDNode>(
C);
2577 if (Z.getOperand(0).getValueType() != MVT::i1)
2589 EVT VT =
C.getValueType();
2602 if ((!LegalOperations || hasOperation(
ISD::AVGCEILU, VT)) &&
2607 if ((!LegalOperations || hasOperation(
ISD::AVGCEILS, VT)) &&
2620 "Expecting add or sub");
2624 bool IsAdd =
N->getOpcode() ==
ISD::ADD;
2625 SDValue ConstantOp = IsAdd ?
N->getOperand(1) :
N->getOperand(0);
2626 SDValue ShiftOp = IsAdd ?
N->getOperand(0) :
N->getOperand(1);
2648 {ConstantOp, DAG.getConstant(1, DL, VT)})) {
2650 Not.getOperand(0), ShAmt);
2692 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
2724 if ((!LegalOperations ||
2727 X.getScalarValueSizeInBits() == 1) {
2743 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
2747 if (!reassociationCanBreakAddressingModePattern(
ISD::ADD,
DL,
N, N0, N1)) {
2835 return (!Max && !
Op) ||
2836 (
Max &&
Op &&
Max->getAPIntValue() == (-
Op->getAPIntValue()));
2877 !
N->getFlags().hasNoSignedWrap()))) {
2898 (CA * CM + CB->getAPIntValue()).getSExtValue())) {
2902 if (
N->getFlags().hasNoUnsignedWrap() &&
2906 if (
N->getFlags().hasNoSignedWrap() &&
2915 DAG.
getConstant(CA * CM + CB->getAPIntValue(),
DL, VT), Flags);
2923 (CA * CM + CB->getAPIntValue()).getSExtValue())) {
2929 if (
N->getFlags().hasNoUnsignedWrap() &&
2934 if (
N->getFlags().hasNoSignedWrap() &&
2945 DAG.
getConstant(CA * CM + CB->getAPIntValue(),
DL, VT), Flags);
2950 if (
SDValue Combined = visitADDLikeCommutative(N0, N1,
N))
2953 if (
SDValue Combined = visitADDLikeCommutative(N1, N0,
N))
2985 if (
SDValue Combined = visitADDLike(
N))
3025 APInt NewStep = C0 + C1;
3035 APInt NewStep = SV0 + SV1;
3044 unsigned Opcode =
N->getOpcode();
3062 return DAG.
getNode(Opcode,
DL, VT, N1, N0);
3066 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
3086 bool ForceCarryReconstruction =
false) {
3092 V = V.getOperand(0);
3097 if (ForceCarryReconstruction)
3101 V = V.getOperand(0);
3105 if (ForceCarryReconstruction && V.getValueType() == MVT::i1)
3112 if (V.getResNo() != 1)
3119 EVT VT = V->getValueType(0);
3227 if (TN->
getVT() == MVT::i1) {
3244 DAG.
getVTList(VT, Carry.getValueType()), N0,
3257 if (!
N->hasAnyUseOfValue(1))
3290 if (Force && isa<ConstantSDNode>(V))
3297 return V.getOperand(0);
3309 EVT CarryVT =
N->getValueType(1);
3313 if (!
N->hasAnyUseOfValue(1))
3320 return DAG.
getNode(
N->getOpcode(),
DL,
N->getVTList(), N1, N0);
3345 if (
SDValue Combined = visitUADDOLike(N0, N1,
N))
3348 if (
SDValue Combined = visitUADDOLike(N1, N0,
N))
3382 SDValue CarryIn =
N->getOperand(2);
3401 SDValue CarryIn =
N->getOperand(2);
3412 if (!LegalOperations ||
3422 AddToWorklist(CarryExt.
getNode());
3428 if (
SDValue Combined = visitUADDO_CARRYLike(N0, N1, CarryIn,
N))
3431 if (
SDValue Combined = visitUADDO_CARRYLike(N1, N0, CarryIn,
N))
3439 SDValue Ops[] = {N1, N0, CarryIn};
3578 EVT CarryOutType =
N->getValueType(0);
3594 unsigned CarryInOperandNum =
3596 if (Opcode ==
ISD::USUBO && CarryInOperandNum != 1)
3690 SDValue CarryIn =
N->getOperand(2);
3701 if (!LegalOperations ||
3706 if (
SDValue Combined = visitSADDO_CARRYLike(N0, N1, CarryIn,
N))
3709 if (
SDValue Combined = visitSADDO_CARRYLike(N1, N0, CarryIn,
N))
3721 "Illegal truncation");
3747 !(!LegalOperations || hasOperation(
ISD::USUBSAT, DstVT)))
3750 EVT SubVT =
N->getValueType(0);
3818template <
class MatchContextClass>
3841 if ((
BitWidth - Src.getValueType().getScalarSizeInBits()) != BitWidthDiff)
3851 if (!(AndMask.
isMask(AndMaskWidth) && XorMask.
countr_one() >= AndMaskWidth))
3882 auto PeekThroughFreeze = [](
SDValue N) {
3884 return N->getOperand(0);
3888 if (
SDValue V = foldSubCtlzNot<EmptyMatchContext>(
N, DAG))
3893 if (PeekThroughFreeze(N0) == PeekThroughFreeze(N1))
3902 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
3910 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
3933 if (
N->getFlags().hasNoUnsignedWrap())
3939 if (
N->getFlags().hasNoSignedWrap())
3965 if (hasOperation(NewOpc, VT))
4092 if (!reassociationCanBreakAddressingModePattern(
ISD::SUB,
DL,
N, N0, N1) &&
4130 if ((!LegalOperations || hasOperation(
ISD::ABS, VT)) &&
4140 if (GA->getGlobal() == GB->getGlobal())
4148 if (TN->
getVT() == MVT::i1) {
4201 DAG.
getVTList(VT, Carry.getValueType()), NegX, Zero,
4209 if (!C0->isOpaque()) {
4210 const APInt &C0Val = C0->getAPIntValue();
4211 const APInt &MaybeOnes = ~DAG.computeKnownBits(N1).Zero;
4212 if ((C0Val - MaybeOnes) == (C0Val ^ MaybeOnes))
4218 if ((!LegalOperations || hasOperation(
ISD::ABDS, VT)) &&
4230 if ((!LegalOperations || hasOperation(
ISD::ABDU, VT)) &&
4245 unsigned Opcode =
N->getOpcode();
4266 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4292 if (!
N->hasAnyUseOfValue(1))
4319 EVT CarryVT =
N->getValueType(1);
4323 if (!
N->hasAnyUseOfValue(1))
4358 SDValue CarryIn =
N->getOperand(2);
4370 SDValue CarryIn =
N->getOperand(2);
4374 if (!LegalOperations ||
4385 SDValue CarryIn =
N->getOperand(2);
4389 if (!LegalOperations ||
4421template <
class MatchContextClass>
SDValue DAGCombiner::visitMUL(
SDNode *
N) {
4427 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
4428 MatchContextClass Matcher(DAG, TLI,
N);
4441 return Matcher.getNode(
ISD::MUL,
DL, VT, N1, N0);
4443 bool N1IsConst =
false;
4444 bool N1IsOpaqueConst =
false;
4451 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4456 "Splat APInt should be element width");
4458 N1IsConst = isa<ConstantSDNode>(N1);
4461 N1IsOpaqueConst = cast<ConstantSDNode>(N1)->isOpaque();
4466 if (N1IsConst && ConstValue1.
isZero())
4470 if (N1IsConst && ConstValue1.
isOne())
4474 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4478 if (N1IsConst && ConstValue1.
isAllOnes())
4484 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
4493 unsigned Log2Val = (-ConstValue1).logBase2();
4497 return Matcher.getNode(
4511 if (LoHi->hasAnyUseOfValue(1))
4514 if (LoHi->hasAnyUseOfValue(1))
4535 if (!UseVP && N1IsConst &&
4543 unsigned TZeros = MulC == 2 ? 0 : MulC.
countr_zero();
4545 if ((MulC - 1).isPowerOf2())
4547 else if ((MulC + 1).isPowerOf2())
4552 MathOp ==
ISD::ADD ? (MulC - 1).logBase2() : (MulC + 1).logBase2();
4555 "multiply-by-constant generated out of bounds shift");
4559 TZeros ? DAG.
getNode(MathOp,
DL, VT, Shl,
4601 return Matcher.getNode(
4619 APInt NewStep = C0 * MulVal;
4625 if (!UseVP && (!LegalOperations || hasOperation(
ISD::ABS, VT)) &&
4642 if (!V ||
V->isZero()) {
4656 for (
unsigned I = 0;
I != NumElts; ++
I)
4687 EVT NodeType =
Node->getValueType(0);
4688 if (!NodeType.isSimple())
4690 switch (NodeType.getSimpleVT().SimpleTy) {
4691 default:
return false;
4692 case MVT::i8: LC=
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
4693 case MVT::i16: LC=
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
4694 case MVT::i32: LC=
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
4695 case MVT::i64: LC=
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
4696 case MVT::i128: LC=
isSigned ? RTLIB::SDIVREM_I128:RTLIB::UDIVREM_I128;
break;
4704 if (
Node->use_empty())
4707 unsigned Opcode =
Node->getOpcode();
4712 EVT VT =
Node->getValueType(0);
4726 unsigned OtherOpcode = 0;
4747 unsigned UserOpc =
User->getOpcode();
4748 if ((UserOpc == Opcode || UserOpc == OtherOpcode || UserOpc == DivRemOpc) &&
4752 if (UserOpc == OtherOpcode) {
4755 }
else if (UserOpc == DivRemOpc) {
4758 assert(UserOpc == Opcode);
4763 CombineTo(
User, combined);
4774 EVT VT =
N->getValueType(0);
4777 unsigned Opc =
N->getOpcode();
4786 if (DAG.
isUndef(Opc, {N0, N1}))
4797 if (N0C && N0C->
isZero())
4820 EVT VT =
N->getValueType(0);
4830 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4847 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4855 if (
SDValue V = visitSDIVLike(N0, N1,
N)) {
4862 AddToWorklist(
Mul.getNode());
4864 CombineTo(RemNode, Sub);
4884 if (
C->isZero() ||
C->isOpaque())
4886 if (
C->getAPIntValue().isPowerOf2())
4888 if (
C->getAPIntValue().isNegatedPowerOf2())
4898 EVT VT =
N->getValueType(0);
4923 AddToWorklist(Sign.
getNode());
4929 AddToWorklist(
Add.getNode());
4940 Sra = DAG.
getSelect(
DL, VT, IsOneOrAllOnes, N0, Sra);
4968 EVT VT =
N->getValueType(0);
4978 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4992 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4995 if (
SDValue V = visitUDIVLike(N0, N1,
N)) {
5002 AddToWorklist(
Mul.getNode());
5004 CombineTo(RemNode, Sub);
5028 EVT VT =
N->getValueType(0);
5032 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
5033 AddToWorklist(LogBase2.getNode());
5037 AddToWorklist(Trunc.
getNode());
5046 if (
SDValue LogBase2 = BuildLogBase2(N10,
DL)) {
5047 AddToWorklist(LogBase2.getNode());
5051 AddToWorklist(Trunc.
getNode());
5053 AddToWorklist(
Add.getNode());
5081 unsigned Opcode =
N->getOpcode();
5084 EVT VT =
N->getValueType(0);
5106 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
5119 AddToWorklist(
Add.getNode());
5130 AddToWorklist(
Add.getNode());
5147 if (
SDValue OptimizedRem = buildOptimizedSREM(N0, N1,
N))
5148 return OptimizedRem;
5152 isSigned ? visitSDIVLike(N0, N1,
N) : visitUDIVLike(N0, N1,
N);
5158 CombineTo(DivNode, OptimizedDiv);
5161 AddToWorklist(OptimizedDiv.
getNode());
5162 AddToWorklist(
Mul.getNode());
5169 return DivRem.getValue(1);
5177 EVT VT =
N->getValueType(0);
5190 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5218 unsigned SimpleSize =
Simple.getSizeInBits();
5236 EVT VT =
N->getValueType(0);
5249 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5273 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
5288 unsigned SimpleSize =
Simple.getSizeInBits();
5310 unsigned Opcode =
N->getOpcode();
5313 EVT VT =
N->getValueType(0);
5324 return DAG.
getNode(Opcode,
DL,
N->getVTList(), N1, N0);
5327 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5353 X.getValueType() ==
Y.getValueType() &&
5354 hasOperation(Opcode,
X.getValueType())) {
5360 X.getValueType() ==
Y.getValueType() &&
5361 hasOperation(Opcode,
X.getValueType())) {
5394 if (IsSigned &&
Add->getFlags().hasNoSignedWrap())
5397 if (!IsSigned &&
Add->getFlags().hasNoUnsignedWrap())
5406 unsigned Opcode =
N->getOpcode();
5409 EVT VT =
N->getValueType(0);
5419 return DAG.
getNode(Opcode,
DL,
N->getVTList(), N1, N0);
5422 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5437 (!LegalOperations || hasOperation(
ISD::ABS, VT)))
5455SDValue DAGCombiner::SimplifyNodeWithTwoResults(
SDNode *
N,
unsigned LoOp,
5458 bool HiExists =
N->hasAnyUseOfValue(1);
5459 if (!HiExists && (!LegalOperations ||
5462 return CombineTo(
N, Res, Res);
5466 bool LoExists =
N->hasAnyUseOfValue(0);
5467 if (!LoExists && (!LegalOperations ||
5470 return CombineTo(
N, Res, Res);
5474 if (LoExists && HiExists)
5480 AddToWorklist(
Lo.getNode());
5483 (!LegalOperations ||
5485 return CombineTo(
N, LoOpt, LoOpt);
5490 AddToWorklist(
Hi.getNode());
5493 (!LegalOperations ||
5495 return CombineTo(
N, HiOpt, HiOpt);
5507 EVT VT =
N->getValueType(0);
5511 if (isa<ConstantSDNode>(N0) && isa<ConstantSDNode>(N1))
5523 unsigned SimpleSize =
Simple.getSizeInBits();
5535 return CombineTo(
N,
Lo,
Hi);
5548 EVT VT =
N->getValueType(0);
5552 if (isa<ConstantSDNode>(N0) && isa<ConstantSDNode>(N1))
5563 return CombineTo(
N, Zero, Zero);
5569 return CombineTo(
N, N0, Zero);
5576 unsigned SimpleSize =
Simple.getSizeInBits();
5588 return CombineTo(
N,
Lo,
Hi);
5601 EVT CarryVT =
N->getValueType(1);
5622 return DAG.
getNode(
N->getOpcode(),
DL,
N->getVTList(), N1, N0);
5634 N->getVTList(), N0, N0);
5641 return CombineTo(
N,
And, Cmp);
5679 unsigned Opcode0 = isSignedMinMax(N0, N1, N2, N3,
CC);
5717 N0CC = cast<CondCodeSDNode>(N0.
getOperand(4))->get();
5733 unsigned Opcode1 = isSignedMinMax(N00, N01, N02, N03, N0CC);
5734 if (!Opcode1 || Opcode0 == Opcode1)
5744 APInt MinCPlus1 = MinC + 1;
5745 if (-MaxC == MinCPlus1 && MinCPlus1.
isPowerOf2()) {
5802 unsigned BW = (C1 + 1).exactLogBase2();
5822 unsigned Opcode =
N->getOpcode();
5836 return DAG.
getNode(Opcode,
DL, VT, N1, N0);
5840 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5844 if (
SDValue RMINMAX = reassociateOps(Opcode,
DL, N0, N1,
N->getFlags()))
5864 return DAG.
getNode(AltOpcode,
DL, VT, N0, N1);
5876 auto ReductionOpcode = [](
unsigned Opcode) {
5890 if (
SDValue SD = reassociateReduction(ReductionOpcode(Opcode), Opcode,
5904 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
5906 unsigned LogicOpcode =
N->getOpcode();
5921 EVT XVT =
X.getValueType();
5931 if (XVT !=
Y.getValueType())
5935 if ((VT.
isVector() || LegalOperations) &&
5948 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
5958 if (XVT !=
Y.getValueType())
5970 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
5991 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6006 return DAG.
getNode(HandOpcode,
DL, VT, Logic0, Logic1, S);
6019 if (XVT.
isInteger() && XVT ==
Y.getValueType() &&
6023 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6040 auto *SVN0 = cast<ShuffleVectorSDNode>(N0);
6041 auto *SVN1 = cast<ShuffleVectorSDNode>(N1);
6042 assert(
X.getValueType() ==
Y.getValueType() &&
6043 "Inputs to shuffles are not the same type");
6049 if (!SVN0->hasOneUse() || !SVN1->hasOneUse() ||
6050 !SVN0->getMask().equals(SVN1->getMask()))
6086 SDValue LL, LR, RL, RR, N0CC, N1CC;
6087 if (!isSetCCEquivalent(N0, LL, LR, N0CC) ||
6088 !isSetCCEquivalent(N1, RL, RR, N1CC))
6092 "Unexpected operand types for bitwise logic op");
6095 "Unexpected operand types for setcc");
6111 if (LR == RR && CC0 == CC1 && IsInteger) {
6116 bool AndEqZero = IsAnd && CC1 ==
ISD::SETEQ && IsZero;
6118 bool AndGtNeg1 = IsAnd && CC1 ==
ISD::SETGT && IsNeg1;
6120 bool OrNeZero = !IsAnd && CC1 ==
ISD::SETNE && IsZero;
6122 bool OrLtZero = !IsAnd && CC1 ==
ISD::SETLT && IsZero;
6128 if (AndEqZero || AndGtNeg1 || OrNeZero || OrLtZero) {
6130 AddToWorklist(
Or.getNode());
6135 bool AndEqNeg1 = IsAnd && CC1 ==
ISD::SETEQ && IsNeg1;
6137 bool AndLtZero = IsAnd && CC1 ==
ISD::SETLT && IsZero;
6139 bool OrNeNeg1 = !IsAnd && CC1 ==
ISD::SETNE && IsNeg1;
6141 bool OrGtNeg1 = !IsAnd && CC1 ==
ISD::SETGT && IsNeg1;
6147 if (AndEqNeg1 || AndLtZero || OrNeNeg1 || OrGtNeg1) {
6149 AddToWorklist(
And.getNode());
6163 AddToWorklist(
Add.getNode());
6190 return !C0->
isOpaque() && !C1->isOpaque() && (CMax - CMin).isPowerOf2();
6208 if (LL == RR && LR == RL) {
6215 if (LL == RL && LR == RR) {
6219 (!LegalOperations ||
6242 bool isFMAXNUMFMINNUM_IEEE,
6243 bool isFMAXNUMFMINNUM) {
6254 isFMAXNUMFMINNUM_IEEE
6262 isFMAXNUMFMINNUM_IEEE
6280 isFMAXNUMFMINNUM_IEEE
6289 isFMAXNUMFMINNUM_IEEE
6299 "Invalid Op to combine SETCC with");
6310 LogicOp,
LHS.getNode(),
RHS.getNode());
6345 (isFMAXNUMFMINNUM_IEEE || isFMAXNUMFMINNUM))) &&
6351 SDValue CommonValue, Operand1, Operand2;
6359 }
else if (LHS1 == RHS1) {
6372 }
else if (RHS0 == LHS1) {
6389 bool IsSigned = isSignedIntSetCC(
CC);
6401 DAG, isFMAXNUMFMINNUM_IEEE, isFMAXNUMFMINNUM);
6405 DAG.
getNode(NewOpcode,
DL, OpVT, Operand1, Operand2);
6406 return DAG.
getSetCC(
DL, VT, MinMaxValue, CommonValue,
CC);
6416 LHS0 == RHS0 && LHS1C && RHS1C && OpVT.
isInteger()) {
6417 const APInt &APLhs = LHS1C->getAPIntValue();
6418 const APInt &APRhs = RHS1C->getAPIntValue();
6422 if (APLhs == (-APRhs) &&
6433 }
else if (TargetPreference &
6454 APInt Dif = MaxC - MinC;
6488 EVT CondVT =
Cond.getValueType();
6499 EVT OpVT =
T.getValueType();
6518 if (
SDValue V = foldLogicOfSetCCs(
true, N0, N1,
DL))
6536 APInt SRLC = SRLI->getAPIntValue();
6548 CombineTo(N0.
getNode(), NewAdd);
6562 EVT LoadResultTy,
EVT &ExtVT) {
6571 if (ExtVT == LoadedVT &&
6572 (!LegalOperations ||
6588 if (LegalOperations &&
6624 if (LdStMemVT.
bitsLT(MemVT))
6629 assert(ShAmt % 8 == 0 &&
"ShAmt is byte offset");
6630 const unsigned ByteShAmt = ShAmt / 8;
6641 if (PtrType == MVT::Untyped || PtrType.
isExtended())
6644 if (isa<LoadSDNode>(LDST)) {
6648 if (!
SDValue(Load, 0).hasOneUse())
6651 if (LegalOperations &&
6660 if (
Load->getNumValues() > 2)
6673 assert(isa<StoreSDNode>(LDST) &&
"It is not a Load nor a Store SDNode");
6679 if (LegalOperations &&
6686bool DAGCombiner::SearchForAndLoads(
SDNode *
N,
6694 if (
Op.getValueType().isVector())
6698 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
6700 (
Mask->getAPIntValue() &
C->getAPIntValue()) !=
C->getAPIntValue())
6705 if (!
Op.hasOneUse())
6708 switch(
Op.getOpcode()) {
6710 auto *
Load = cast<LoadSDNode>(
Op);
6712 if (isAndLoadExtLoad(Mask, Load,
Load->getValueType(0), ExtVT) &&
6730 unsigned ActiveBits =
Mask->getAPIntValue().countr_one();
6733 cast<VTSDNode>(
Op.getOperand(1))->getVT() :
6734 Op.getOperand(0).getValueType();
6745 if (!SearchForAndLoads(
Op.getNode(), Loads, NodesWithConsts, Mask,
6756 NodeToMask =
Op.getNode();
6759 for (
unsigned i = 0, e = NodeToMask->
getNumValues(); i < e; ++i) {
6761 if (VT != MVT::Glue && VT != MVT::Other) {
6763 NodeToMask =
nullptr;
6775bool DAGCombiner::BackwardsPropagateMask(
SDNode *
N) {
6776 auto *
Mask = dyn_cast<ConstantSDNode>(
N->getOperand(1));
6780 if (!
Mask->getAPIntValue().isMask())
6784 if (isa<LoadSDNode>(
N->getOperand(0)))
6789 SDNode *FixupNode =
nullptr;
6790 if (SearchForAndLoads(
N, Loads, NodesWithConsts, Mask, FixupNode)) {
6803 SDValue(FixupNode, 0), MaskOp);
6805 if (
And.getOpcode() == ISD ::AND)
6810 for (
auto *LogicN : NodesWithConsts) {
6814 if (isa<ConstantSDNode>(Op0))
6818 if (isa<ConstantSDNode>(Op1))
6822 if (isa<ConstantSDNode>(Op0) && !isa<ConstantSDNode>(Op1))
6829 for (
auto *Load : Loads) {
6834 if (
And.getOpcode() == ISD ::AND)
6837 SDValue NewLoad = reduceLoadWidth(
And.getNode());
6839 "Shouldn't be masking the load if it can't be narrowed");
6840 CombineTo(Load, NewLoad, NewLoad.
getValue(1));
6853SDValue DAGCombiner::unfoldExtremeBitClearingToShifts(
SDNode *
N) {
6864 unsigned OuterShift;
6865 unsigned InnerShift;
6867 auto matchMask = [&OuterShift, &InnerShift, &
Y](
SDValue M) ->
bool {
6870 OuterShift =
M->getOpcode();
6879 Y =
M->getOperand(1);
6886 else if (matchMask(N0))
6892 EVT VT =
N->getValueType(0);
6909 SDValue And0 =
And->getOperand(0), And1 =
And->getOperand(1);
6919 bool FoundNot =
false;
6922 Src = Src.getOperand(0);
6928 Src = Src.getOperand(0);
6932 if (Src.getOpcode() !=
ISD::SRL || !Src.hasOneUse())
6936 EVT SrcVT = Src.getValueType();
6943 SDValue ShiftAmt = Src.getOperand(1);
6944 auto *ShiftAmtC = dyn_cast<ConstantSDNode>(ShiftAmt);
6945 if (!ShiftAmtC || !ShiftAmtC->getAPIntValue().ult(
BitWidth))
6949 Src = Src.getOperand(0);
6956 Src = Src.getOperand(0);
6980 EVT VT =
N->getValueType(0);
7006 unsigned LogicOpcode =
N->getOpcode();
7008 "Expected bitwise logic operation");
7014 unsigned ShiftOpcode = ShiftOp.
getOpcode();
7015 if (LogicOp.
getOpcode() != LogicOpcode ||
7039 EVT VT =
N->getValueType(0);
7043 return DAG.
getNode(LogicOpcode,
DL, VT, NewShift, Z);
7054 unsigned LogicOpcode =
N->getOpcode();
7056 "Expected bitwise logic operation");
7057 if (LeftHand.
getOpcode() != LogicOpcode ||
7078 EVT VT =
N->getValueType(0);
7080 return DAG.
getNode(LogicOpcode,
DL, VT, CombinedShifts, W);
7107 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
7121 auto *MLoad = dyn_cast<MaskedLoadSDNode>(N0);
7124 EVT LoadVT = MLoad->getMemoryVT();
7132 if (
Splat->getAPIntValue().isMask(ElementSize)) {
7134 ExtVT,
DL, MLoad->getChain(), MLoad->getBasePtr(),
7135 MLoad->getOffset(), MLoad->getMask(), MLoad->getPassThru(),
7136 LoadVT, MLoad->getMemOperand(), MLoad->getAddressingMode(),
7138 bool LoadHasOtherUsers = !N0.
hasOneUse();
7139 CombineTo(
N, NewLoad);
7140 if (LoadHasOtherUsers)
7161 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
7175 return RHS->getAPIntValue().isSubsetOf(
LHS->getAPIntValue());
7243 unsigned EltBitWidth =
Vector->getValueType(0).getScalarSizeInBits();
7244 APInt SplatValue, SplatUndef;
7245 unsigned SplatBitSize;
7252 const bool IsBigEndian =
false;
7254 Vector->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
7255 HasAnyUndefs, EltBitWidth, IsBigEndian);
7259 if (IsSplat && (SplatBitSize % EltBitWidth) == 0) {
7262 SplatValue |= SplatUndef;
7269 for (
unsigned i = 0, n = (SplatBitSize / EltBitWidth); i < n; ++i)
7278 Load->getValueType(0),
7279 Load->getMemoryVT());
7287 switch (
Load->getExtensionType()) {
7288 default:
B =
false;
break;
7300 CombineTo(
N, (N0.
getNode() == Load) ? NewLoad : N0);
7305 Load->getChain(),
Load->getBasePtr(),
7306 Load->getOffset(),
Load->getMemoryVT(),
7307 Load->getMemOperand());
7309 if (
Load->getNumValues() == 3) {
7313 CombineTo(Load, To, 3,
true);
7315 CombineTo(Load, NewLoad.getValue(0), NewLoad.getValue(1));
7325 if (
SDValue Shuffle = XformToShuffleWithZero(
N))
7334 EVT ExtVT =
Ext->getValueType(0);
7351 if (
auto *GN0 = dyn_cast<MaskedGatherSDNode>(N0)) {
7352 EVT MemVT = GN0->getMemoryVT();
7355 if (
SDValue(GN0, 0).hasOneUse() &&
7358 SDValue Ops[] = {GN0->getChain(), GN0->getPassThru(), GN0->getMask(),
7359 GN0->getBasePtr(), GN0->getIndex(), GN0->getScale()};
7362 DAG.
getVTList(VT, MVT::Other), MemVT,
DL, Ops, GN0->getMemOperand(),
7365 CombineTo(
N, ZExtLoad);
7366 AddToWorklist(ZExtLoad.
getNode());
7375 if (
SDValue Res = reduceLoadWidth(
N))
7383 if (BackwardsPropagateMask(
N))
7387 if (
SDValue Combined = visitANDLike(N0, N1,
N))
7392 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
7439 X.getOperand(0).getScalarValueSizeInBits() == 1)
7442 X.getOperand(0).getScalarValueSizeInBits() == 1)
7456 auto *LN0 = cast<LoadSDNode>(N0);
7457 EVT MemVT = LN0->getMemoryVT();
7464 ((!LegalOperations && LN0->isSimple()) ||
7468 LN0->getBasePtr(), MemVT, LN0->getMemOperand());
7482 if (
SDValue Shifts = unfoldExtremeBitClearingToShifts(
N))
7498 auto *
C = dyn_cast<ConstantSDNode>(RHS);
7502 if (!
C->getAPIntValue().isMask(
7503 LHS.getOperand(0).getValueType().getFixedSizeInBits()))
7510 if (IsAndZeroExtMask(N0, N1))
7519 if (LegalOperations || VT.
isVector())
7528 bool DemandHighBits) {
7529 if (!LegalOperations)
7532 EVT VT =
N->getValueType(0);
7533 if (VT != MVT::i64 && VT != MVT::i32 && VT != MVT::i16)
7539 bool LookPassAnd0 =
false;
7540 bool LookPassAnd1 =
false;
7555 LookPassAnd0 =
true;
7565 LookPassAnd1 =
true;
7591 LookPassAnd0 =
true;
7605 LookPassAnd1 =
true;
7614 if (OpSizeInBits > 16) {
7618 if (DemandHighBits && !LookPassAnd0)
7625 if (!LookPassAnd1) {
7626 unsigned HighBit = DemandHighBits ? OpSizeInBits : 24;
7634 if (OpSizeInBits > 16) {
7649 if (!
N->hasOneUse())
7652 unsigned Opc =
N.getOpcode();
7664 N1C = dyn_cast<ConstantSDNode>(
N.getOperand(1));
7666 N1C = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
7670 unsigned MaskByteOffset;
7674 case 0xFF: MaskByteOffset = 0;
break;
7675 case 0xFF00: MaskByteOffset = 1;
break;
7684 case 0xFF0000: MaskByteOffset = 2;
break;
7685 case 0xFF000000: MaskByteOffset = 3;
break;
7690 if (MaskByteOffset == 0 || MaskByteOffset == 2) {
7696 if (!
C ||
C->getZExtValue() != 8)
7704 if (!
C ||
C->getZExtValue() != 8)
7710 if (MaskByteOffset != 0 && MaskByteOffset != 2)
7713 if (!
C ||
C->getZExtValue() != 8)
7718 if (MaskByteOffset != 1 && MaskByteOffset != 3)
7721 if (!
C ||
C->getZExtValue() != 8)
7725 if (Parts[MaskByteOffset])
7740 if (!
C ||
C->getAPIntValue() != 16)
7742 Parts[0] = Parts[1] =
N.getOperand(0).getOperand(0).getNode();
7757 "MatchBSwapHWordOrAndAnd: expecting i32");
7767 if (!Mask0 || !Mask1)
7778 if (!ShiftAmt0 || !ShiftAmt1)
7798 if (!LegalOperations)
7801 EVT VT =
N->getValueType(0);
7839 if (Parts[0] != Parts[1] || Parts[0] != Parts[2] || Parts[0] != Parts[3])
7867 if (
SDValue V = foldLogicOfSetCCs(
false, N0, N1,
DL))
7882 const APInt &LHSMask = N0O1C->getAPIntValue();
7883 const APInt &RHSMask = N1O1C->getAPIntValue();
7917 auto peekThroughResize = [](
SDValue V) {
7919 return V->getOperand(0);
7923 SDValue N0Resized = peekThroughResize(N0);
7925 SDValue N1Resized = peekThroughResize(N1);
7930 if (N00 == N1Resized || N01 == N1Resized)
7937 if (peekThroughResize(NotOperand) == N1Resized)
7945 if (peekThroughResize(NotOperand) == N1Resized)
7966 auto peekThroughZext = [](
SDValue V) {
7968 return V->getOperand(0);
7990 Lo.getScalarValueSizeInBits() == (BW / 2) &&
7991 Lo.getValueType() ==
Hi.getValueType()) {
8028 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
8042 auto *SV0 = dyn_cast<ShuffleVectorSDNode>(N0);
8043 auto *SV1 = dyn_cast<ShuffleVectorSDNode>(N1);
8050 if ((ZeroN00 != ZeroN01) && (ZeroN10 != ZeroN11)) {
8051 assert((!ZeroN00 || !ZeroN01) &&
"Both inputs zero!");
8052 assert((!ZeroN10 || !ZeroN11) &&
"Both inputs zero!");
8053 bool CanFold =
true;
8057 for (
int i = 0; i != NumElts; ++i) {
8058 int M0 = SV0->getMaskElt(i);
8059 int M1 = SV1->getMaskElt(i);
8062 bool M0Zero =
M0 < 0 || (ZeroN00 == (
M0 < NumElts));
8063 bool M1Zero =
M1 < 0 || (ZeroN10 == (
M1 < NumElts));
8067 if ((M0Zero &&
M1 < 0) || (M1Zero &&
M0 < 0))
8071 if (M0Zero == M1Zero) {
8076 assert((
M0 >= 0 ||
M1 >= 0) &&
"Undef index!");
8082 Mask[i] = M1Zero ?
M0 % NumElts : (
M1 % NumElts) + NumElts;
8091 return LegalShuffle;
8105 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
8116 if (
SDValue Combined = visitORLike(N0, N1,
DL))
8123 if (
SDValue BSwap = MatchBSwapHWord(
N, N0, N1))
8125 if (
SDValue BSwap = MatchBSwapHWordLow(
N, N0, N1))
8159 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
8163 if (
SDValue Rot = MatchRotate(N0, N1,
DL))
8166 if (
SDValue Load = MatchLoadCombine(
N))
8176 if (
SDValue Combined = visitADDLike(
N))
8181 if (LegalOperations || VT.
isVector())
8192 Mask =
Op.getOperand(1);
8193 return Op.getOperand(0);
8236 assert(OppShift && ExtractFrom &&
"Empty SDValue");
8264 bool IsMulOrDiv =
false;
8267 auto SelectOpcode = [&](
unsigned NeededShift,
unsigned MulOrDivVariant) {
8268 IsMulOrDiv = ExtractFrom.
getOpcode() == MulOrDivVariant;
8269 if (!IsMulOrDiv && ExtractFrom.
getOpcode() != NeededShift)
8271 Opcode = NeededShift;
8321 if (Rem != 0 || ResultAmt != OppLHSAmt)
8327 if (OppLHSAmt != ExtractFromAmt - NeededShiftAmt.
zextOrTrunc(
8336 return DAG.
getNode(Opcode,
DL, ResVT, OppShiftLHS, NewShiftNode);
8390 unsigned MaskLoBits = 0;
8392 unsigned Bits =
Log2_64(EltSize);
8394 if (NegBits >= Bits) {
8417 if (PosBits >= MaskLoBits) {
8439 if ((Pos == NegOp1) ||
8463 return Width.
getLoBits(MaskLoBits) == 0;
8464 return Width == EltSize;
8474 SDValue InnerNeg,
bool HasPos,
8475 unsigned PosOpcode,
unsigned NegOpcode,
8487 return DAG.
getNode(HasPos ? PosOpcode : NegOpcode,
DL, VT, Shifted,
8488 HasPos ? Pos : Neg);
8502 SDValue InnerNeg,
bool HasPos,
8503 unsigned PosOpcode,
unsigned NegOpcode,
8515 if (
matchRotateSub(InnerPos, InnerNeg, EltBits, DAG, N0 == N1)) {
8516 return DAG.
getNode(HasPos ? PosOpcode : NegOpcode,
DL, VT, N0, N1,
8517 HasPos ? Pos : Neg);
8524 auto IsBinOpImm = [](
SDValue Op,
unsigned BinOpc,
unsigned Imm) {
8525 if (
Op.getOpcode() != BinOpc)
8534 IsBinOpImm(InnerNeg,
ISD::XOR, EltBits - 1) &&
8543 IsBinOpImm(InnerPos,
ISD::XOR, EltBits - 1) &&
8553 IsBinOpImm(InnerPos,
ISD::XOR, EltBits - 1) &&
8568 EVT VT =
LHS.getValueType();
8573 bool HasROTL = hasOperation(
ISD::ROTL, VT);
8574 bool HasROTR = hasOperation(
ISD::ROTR, VT);
8575 bool HasFSHL = hasOperation(
ISD::FSHL, VT);
8576 bool HasFSHR = hasOperation(
ISD::FSHR, VT);
8587 if (LegalOperations && !HasROTL && !HasROTR && !HasFSHL && !HasFSHR)
8592 LHS.getOperand(0).getValueType() ==
RHS.getOperand(0).getValueType()) {
8594 if (
SDValue Rot = MatchRotate(
LHS.getOperand(0),
RHS.getOperand(0),
DL)) {
8609 if (!LHSShift && !RHSShift)
8624 RHSShift = NewRHSShift;
8629 LHSShift = NewLHSShift;
8632 if (!RHSShift || !LHSShift)
8659 return (
LHS->getAPIntValue() +
RHS->getAPIntValue()) == EltSizeInBits;
8662 auto ApplyMasks = [&](
SDValue Res) {
8686 bool IsRotate = LHSShiftArg == RHSShiftArg;
8687 if (!IsRotate && !(HasFSHL || HasFSHR)) {
8696 if (CommonOp ==
Or.getOperand(0)) {
8698 Y =
Or.getOperand(1);
8701 if (CommonOp ==
Or.getOperand(1)) {
8703 Y =
Or.getOperand(0);
8710 if (matchOr(LHSShiftArg, RHSShiftArg)) {
8715 }
else if (matchOr(RHSShiftArg, LHSShiftArg)) {
8724 return ApplyMasks(Res);
8737 if (IsRotate && (HasROTL || HasROTR || !(HasFSHL || HasFSHR))) {
8738 bool UseROTL = !LegalOperations || HasROTL;
8740 UseROTL ? LHSShiftAmt : RHSShiftAmt);
8742 bool UseFSHL = !LegalOperations || HasFSHL;
8744 RHSShiftArg, UseFSHL ? LHSShiftAmt : RHSShiftAmt);
8747 return ApplyMasks(Res);
8752 if (!HasROTL && !HasROTR && !HasFSHL && !HasFSHR)
8761 SDValue LExtOp0 = LHSShiftAmt;
8762 SDValue RExtOp0 = RHSShiftAmt;
8775 if (IsRotate && (HasROTL || HasROTR)) {
8777 MatchRotatePosNeg(LHSShiftArg, LHSShiftAmt, RHSShiftAmt, LExtOp0,
8783 MatchRotatePosNeg(RHSShiftArg, RHSShiftAmt, LHSShiftAmt, RExtOp0,
8790 MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, LHSShiftAmt, RHSShiftAmt,
8796 MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, RHSShiftAmt, LHSShiftAmt,
8847static std::optional<SDByteProvider>
8849 std::optional<uint64_t> VectorIndex,
8850 unsigned StartingIndex = 0) {
8854 return std::nullopt;
8858 if (
Depth && !
Op.hasOneUse() &&
8859 (
Op.getOpcode() !=
ISD::LOAD || !
Op.getValueType().isVector()))
8860 return std::nullopt;
8864 if (
Op.getOpcode() !=
ISD::LOAD && VectorIndex.has_value())
8865 return std::nullopt;
8869 return std::nullopt;
8871 assert(Index < ByteWidth &&
"invalid index requested");
8874 switch (
Op.getOpcode()) {
8879 return std::nullopt;
8883 return std::nullopt;
8885 if (
LHS->isConstantZero())
8887 if (
RHS->isConstantZero())
8889 return std::nullopt;
8892 auto ShiftOp = dyn_cast<ConstantSDNode>(
Op->getOperand(1));
8894 return std::nullopt;
8896 uint64_t BitShift = ShiftOp->getZExtValue();
8898 if (BitShift % 8 != 0)
8899 return std::nullopt;
8905 return Index < ByteShift
8908 Depth + 1, VectorIndex, Index);
8915 if (NarrowBitWidth % 8 != 0)
8916 return std::nullopt;
8917 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
8919 if (Index >= NarrowByteWidth)
8921 ? std::optional<SDByteProvider>(
8929 Depth + 1, VectorIndex, StartingIndex);
8931 auto OffsetOp = dyn_cast<ConstantSDNode>(
Op->getOperand(1));
8933 return std::nullopt;
8935 VectorIndex = OffsetOp->getZExtValue();
8939 if (NarrowBitWidth % 8 != 0)
8940 return std::nullopt;
8941 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
8944 if (Index >= NarrowByteWidth)
8945 return std::nullopt;
8953 if (*VectorIndex * NarrowByteWidth > StartingIndex)
8954 return std::nullopt;
8955 if ((*VectorIndex + 1) * NarrowByteWidth <= StartingIndex)
8956 return std::nullopt;
8959 VectorIndex, StartingIndex);
8962 auto L = cast<LoadSDNode>(
Op.getNode());
8963 if (!L->isSimple() || L->isIndexed())
8964 return std::nullopt;
8966 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
8967 if (NarrowBitWidth % 8 != 0)
8968 return std::nullopt;
8969 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
8974 if (Index >= NarrowByteWidth)
8976 ? std::optional<SDByteProvider>(
8980 unsigned BPVectorIndex = VectorIndex.value_or(0U);
8985 return std::nullopt;
9000 int64_t FirstOffset) {
9002 unsigned Width = ByteOffsets.
size();
9004 return std::nullopt;
9006 bool BigEndian =
true, LittleEndian =
true;
9007 for (
unsigned i = 0; i < Width; i++) {
9008 int64_t CurrentByteOffset = ByteOffsets[i] - FirstOffset;
9011 if (!BigEndian && !LittleEndian)
9012 return std::nullopt;
9015 assert((BigEndian != LittleEndian) &&
"It should be either big endian or"
9022 switch (
Value.getOpcode()) {
9027 return Value.getOperand(0);
9065 EVT MemVT =
N->getMemoryVT();
9066 if (!(MemVT == MVT::i8 || MemVT == MVT::i16 || MemVT == MVT::i32) ||
9067 !
N->isSimple() ||
N->isIndexed())
9074 unsigned MaxWideNumBits = 64;
9075 unsigned MaxStores = MaxWideNumBits / NarrowNumBits;
9076 while (
auto *Store = dyn_cast<StoreSDNode>(Chain)) {
9084 if (
Store->getMemoryVT() != MemVT || !
Store->isSimple() ||
9088 Chain =
Store->getChain();
9089 if (MaxStores < Stores.
size())
9093 if (Stores.
size() < 2)
9098 unsigned NumStores = Stores.
size();
9099 unsigned WideNumBits = NumStores * NarrowNumBits;
9101 if (WideVT != MVT::i16 && WideVT != MVT::i32 && WideVT != MVT::i64)
9110 std::optional<BaseIndexOffset>
Base;
9111 for (
auto *Store : Stores) {
9122 isa<ConstantSDNode>(WideVal.
getOperand(1))) {
9130 if (ShiftAmtC % NarrowNumBits != 0)
9137 Offset = ShiftAmtC / NarrowNumBits;
9143 SourceValue = WideVal;
9144 else if (SourceValue != WideVal) {
9152 SourceValue = WideVal;
9161 int64_t ByteOffsetFromBase = 0;
9164 else if (!
Base->equalBaseIndex(
Ptr, DAG, ByteOffsetFromBase))
9168 if (ByteOffsetFromBase < FirstOffset) {
9170 FirstOffset = ByteOffsetFromBase;
9174 if (Offset < 0 || Offset >= NumStores || OffsetMap[
Offset] !=
INT64_MAX)
9176 OffsetMap[
Offset] = ByteOffsetFromBase;
9180 assert(FirstStore &&
"First store must be set");
9187 if (!Allowed || !
Fast)
9192 auto checkOffsets = [&](
bool MatchLittleEndian) {
9193 if (MatchLittleEndian) {
9194 for (
unsigned i = 0; i != NumStores; ++i)
9195 if (OffsetMap[i] != i * (NarrowNumBits / 8) + FirstOffset)
9198 for (
unsigned i = 0, j = NumStores - 1; i != NumStores; ++i, --
j)
9199 if (OffsetMap[j] != i * (NarrowNumBits / 8) + FirstOffset)
9206 bool NeedBswap =
false;
9207 bool NeedRotate =
false;
9210 if (NarrowNumBits == 8 && checkOffsets(Layout.
isBigEndian()))
9212 else if (NumStores == 2 && checkOffsets(Layout.
isBigEndian()))
9221 "Unexpected store value to merge");
9230 }
else if (NeedRotate) {
9231 assert(WideNumBits % 2 == 0 &&
"Unexpected type for rotate");
9277 "Can only match load combining against OR nodes");
9280 EVT VT =
N->getValueType(0);
9281 if (VT != MVT::i16 && VT != MVT::i32 && VT != MVT::i64)
9287 assert(
P.hasSrc() &&
"Must be a memory byte provider");
9288 auto *
Load = cast<LoadSDNode>(
P.Src.value());
9290 unsigned LoadBitWidth =
Load->getMemoryVT().getScalarSizeInBits();
9292 assert(LoadBitWidth % 8 == 0 &&
9293 "can only analyze providers for individual bytes not bit");
9294 unsigned LoadByteWidth = LoadBitWidth / 8;
9299 std::optional<BaseIndexOffset>
Base;
9303 std::optional<SDByteProvider> FirstByteProvider;
9309 unsigned ZeroExtendedBytes = 0;
9310 for (
int i = ByteWidth - 1; i >= 0; --i) {
9317 if (
P->isConstantZero()) {
9320 if (++ZeroExtendedBytes != (ByteWidth -
static_cast<unsigned>(i)))
9324 assert(
P->hasSrc() &&
"provenance should either be memory or zero");
9325 auto *
L = cast<LoadSDNode>(
P->Src.value());
9331 else if (Chain != LChain)
9336 int64_t ByteOffsetFromBase = 0;
9345 if (
L->getMemoryVT().isVector()) {
9346 unsigned LoadWidthInBit =
L->getMemoryVT().getScalarSizeInBits();
9347 if (LoadWidthInBit % 8 != 0)
9349 unsigned ByteOffsetFromVector =
P->SrcOffset * LoadWidthInBit / 8;
9350 Ptr.addToOffset(ByteOffsetFromVector);
9356 else if (!
Base->equalBaseIndex(
Ptr, DAG, ByteOffsetFromBase))
9360 ByteOffsetFromBase += MemoryByteOffset(*
P);
9361 ByteOffsets[i] = ByteOffsetFromBase;
9364 if (ByteOffsetFromBase < FirstOffset) {
9365 FirstByteProvider =
P;
9366 FirstOffset = ByteOffsetFromBase;
9372 assert(!Loads.
empty() &&
"All the bytes of the value must be loaded from "
9373 "memory, so there must be at least one load which produces the value");
9374 assert(
Base &&
"Base address of the accessed memory location must be set");
9377 bool NeedsZext = ZeroExtendedBytes > 0;
9388 if (LegalOperations &&
9396 ArrayRef(ByteOffsets).drop_back(ZeroExtendedBytes), FirstOffset);
9400 assert(FirstByteProvider &&
"must be set");
9404 if (MemoryByteOffset(*FirstByteProvider) != 0)
9406 auto *FirstLoad = cast<LoadSDNode>(FirstByteProvider->Src.value());
9413 bool NeedsBswap = IsBigEndianTarget != *IsBigEndian;
9420 if (NeedsBswap && (LegalOperations || NeedsZext) &&
9426 if (NeedsBswap && NeedsZext && LegalOperations &&
9434 *FirstLoad->getMemOperand(), &
Fast);
9435 if (!Allowed || !
Fast)
9440 Chain, FirstLoad->getBasePtr(),
9441 FirstLoad->getPointerInfo(), MemVT, FirstLoad->getAlign());
9481 EVT VT =
N->getValueType(0);
9503 M =
And.getOperand(XorIdx ? 0 : 1);
9509 if (!matchAndXor(N0, 0, N1) && !matchAndXor(N0, 1, N1) &&
9510 !matchAndXor(N1, 0, N0) && !matchAndXor(N1, 1, N0))
9516 if (isa<ConstantSDNode>(
M.getNode()))
9584 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
9596 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
9617 if (
SDValue Combined = visitADDLike(
N))
9624 isSetCCEquivalent(N0, LHS, RHS,
CC,
true)) {
9626 LHS.getValueType());
9627 if (!LegalOperations ||
9645 CombineTo(
N, SetCC);
9647 recursivelyDeleteUnusedNodes(N0.
getNode());
9663 AddToWorklist(
V.getNode());
9672 if (isOneUseSetCC(N01) || isOneUseSetCC(N00)) {
9677 return DAG.
getNode(NewOpcode,
DL, VT, N00, N01);
9685 if (isa<ConstantSDNode>(N01) || isa<ConstantSDNode>(N00)) {
9690 return DAG.
getNode(NewOpcode,
DL, VT, N00, N01);
9713 AddToWorklist(NotX.
getNode());
9718 if (!LegalOperations || hasOperation(
ISD::ABS, VT)) {
9722 SDValue A0 =
A.getOperand(0), A1 =
A.getOperand(1);
9724 if ((A0 == S && A1 == S0) || (A1 == S && A0 == S0))
9761 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
9772 if (
SDValue MM = unfoldMaskedMerge(
N))
9795 unsigned LogicOpcode = LogicOp.
getOpcode();
9801 unsigned ShiftOpcode = Shift->
getOpcode();
9804 assert(C1Node &&
"Expected a shift with constant operand");
9807 const APInt *&ShiftAmtVal) {
9808 if (V.getOpcode() != ShiftOpcode || !V.hasOneUse())
9816 ShiftOp = V.getOperand(0);
9821 if (ShiftAmtVal->getBitWidth() != C1Val.
getBitWidth())
9826 bool Overflow =
false;
9827 APInt NewShiftAmt = C1Val.
uadd_ov(*ShiftAmtVal, Overflow);
9832 if (NewShiftAmt.
uge(V.getScalarValueSizeInBits()))
9841 if (matchFirstShift(LogicOp.
getOperand(0),
X, C0Val))
9843 else if (matchFirstShift(LogicOp.
getOperand(1),
X, C0Val))
9855 return DAG.
getNode(LogicOpcode,
DL, VT, NewShift1, NewShift2,
9885 switch (
LHS.getOpcode()) {
9905 isa<ConstantSDNode>(BinOpLHSVal.
getOperand(1));
9909 if (!IsShiftByConstant && !IsCopyOrSelect)
9912 if (IsCopyOrSelect &&
N->hasOneUse())
9917 EVT VT =
N->getValueType(0);
9919 N->getOpcode(),
DL, VT, {LHS.getOperand(1), N->getOperand(1)})) {
9922 return DAG.
getNode(
LHS.getOpcode(),
DL, VT, NewShift, NewRHS);
9933 EVT TruncVT =
N->getValueType(0);
9934 if (
N->hasOneUse() &&
N->getOperand(0).hasOneUse() &&
9936 SDValue N01 =
N->getOperand(0).getOperand(1);
9939 SDValue N00 =
N->getOperand(0).getOperand(0);
9942 AddToWorklist(Trunc00.
getNode());
9943 AddToWorklist(Trunc01.
getNode());
9955 EVT VT =
N->getValueType(0);
9970 bool OutOfRange =
false;
9972 OutOfRange |=
C->getAPIntValue().uge(Bitsize);
9980 return DAG.
getNode(
N->getOpcode(), dl, VT, N0, Amt);
9985 if (RotAmtC && RotAmtC->getAPIntValue() == 8 &&
9997 return DAG.
getNode(
N->getOpcode(), dl, VT, N0, NewOp1);
10009 bool SameSide = (
N->getOpcode() == NextOp);
10016 if (Norm1 && Norm2)
10018 CombineOp, dl, ShiftVT, {Norm1, Norm2})) {
10020 {CombinedShift, BitsizeC});
10022 ISD::UREM, dl, ShiftVT, {CombinedShift, BitsizeC});
10024 CombinedShiftNorm);
10048 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10071 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10081 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10092 return (c1 + c2).uge(OpSizeInBits);
10102 return (c1 + c2).ult(OpSizeInBits);
10129 return c2.
uge(OpSizeInBits - InnerBitwidth) &&
10130 (c1 + c2).uge(OpSizeInBits);
10142 return c2.
uge(OpSizeInBits - InnerBitwidth) &&
10143 (c1 + c2).ult(OpSizeInBits);
10167 return c1.
ult(VT.getScalarSizeInBits()) && (c1 == c2);
10175 AddToWorklist(NewSHL.
getNode());
10183 const APInt &LHSC =
LHS->getAPIntValue();
10184 const APInt &RHSC =
RHS->getAPIntValue();
10185 return LHSC.
ult(OpSizeInBits) && RHSC.
ult(OpSizeInBits) &&
10257 AddToWorklist(Shl0.
getNode());
10276 {Add.getOperand(1)})) {
10296 if (
SDValue NewSHL = visitShiftByConstant(
N))
10330 APInt NewStep = C0 << ShlVal;
10345 "SRL or SRA node is required here!");
10354 SDValue ShiftOperand =
N->getOperand(0);
10365 if (!IsSignExt && !IsZeroExt)
10372 auto UserOfLowerBits = [NarrowVTSize](
SDNode *U) {
10377 if (!UShiftAmtSrc) {
10381 return UShiftAmt < NarrowVTSize;
10395 unsigned ActiveBits = IsSignExt
10396 ?
Constant->getAPIntValue().getSignificantBits()
10397 :
Constant->getAPIntValue().getActiveBits();
10398 if (ActiveBits > NarrowVTSize)
10415 "Cannot have a multiply node with two different operand types.");
10426 if (ShiftAmt != NarrowVTSize)
10448 bool IsSigned =
N->getOpcode() ==
ISD::SRA;
10455 unsigned Opcode =
N->getOpcode();
10460 EVT VT =
N->getValueType(0);
10510 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10513 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10529 APInt Sum = c1 + c2;
10530 unsigned ShiftSum =
10541 "Expected matchBinaryPredicate to return one element for "
10545 ShiftValue = ShiftValues[0];
10573 if ((ShiftAmt > 0) &&
10583 N->getValueType(0), Trunc);
10618 DAG.
getConstant(AddC->getAPIntValue().lshr(ShiftAmt).trunc(
10635 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10652 if (LargeShift->getAPIntValue() == TruncBits) {
10673 if (
SDValue NewSRA = visitShiftByConstant(
N))
10682 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
10685 if (
SDValue AVG = foldShiftToAvg(
N))
10708 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10711 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10727 return (c1 + c2).uge(OpSizeInBits);
10737 return (c1 + c2).ult(OpSizeInBits);
10757 if (c1 + OpSizeInBits == InnerShiftSize) {
10758 if (c1 + c2 >= InnerShiftSize)
10768 c1 + c2 < InnerShiftSize) {
10773 OpSizeInBits - c2),
10788 const APInt &LHSC =
LHS->getAPIntValue();
10789 const APInt &RHSC =
RHS->getAPIntValue();
10790 return LHSC.
ult(OpSizeInBits) && RHSC.
ult(OpSizeInBits) &&
10831 AddToWorklist(SmallShift.
getNode());
10859 APInt UnknownBits = ~Known.Zero;
10875 AddToWorklist(
Op.getNode());
10884 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10894 if (
SDValue NewSRL = visitShiftByConstant(
N))
10898 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
10925 if (
N->hasOneUse()) {
10934 AddToWorklist(
User);
10942 if (
SDValue AVG = foldShiftToAvg(
N))
10949 EVT VT =
N->getValueType(0);
10962 return IsFSHL ? N0 : N1;
10964 auto IsUndefOrZero = [](
SDValue V) {
10975 return DAG.
getNode(
N->getOpcode(),
DL, VT, N0, N1,
10981 return IsFSHL ? N0 : N1;
10987 if (IsUndefOrZero(N0))
10991 if (IsUndefOrZero(N1))
11003 auto *
LHS = dyn_cast<LoadSDNode>(N0);
11004 auto *
RHS = dyn_cast<LoadSDNode>(N1);
11005 if (LHS && RHS &&
LHS->isSimple() &&
RHS->isSimple() &&
11006 LHS->getAddressSpace() ==
RHS->getAddressSpace() &&
11016 RHS->getAddressSpace(), NewAlign,
11017 RHS->getMemOperand()->getFlags(), &
Fast) &&
11021 AddToWorklist(NewPtr.
getNode());
11023 VT,
DL,
RHS->getChain(), NewPtr,
11024 RHS->getPointerInfo().getWithOffset(PtrOff), NewAlign,
11025 RHS->getMemOperand()->getFlags(),
RHS->getAAInfo());
11027 WorklistRemover DeadNodes(*
this);
11054 if (N0 == N1 && hasOperation(RotOpc, VT))
11055 return DAG.
getNode(RotOpc,
DL, VT, N0, N2);
11100 EVT SrcVT =
N->getValueType(0);
11103 N =
N->getOperand(0).getNode();
11108 EVT VT =
N->getValueType(0);
11109 SDValue AbsOp1 =
N->getOperand(0);
11137 VT0 = cast<VTSDNode>(Op0.
getOperand(1))->getVT();
11138 VT1 = cast<VTSDNode>(Op1.
getOperand(1))->getVT();
11147 EVT MaxVT = VT0.
bitsGT(VT1) ? VT0 : VT1;
11148 if ((VT0 == MaxVT || Op0->
hasOneUse()) &&
11150 (!LegalTypes || hasOperation(ABDOpcode, MaxVT))) {
11160 if (!LegalOperations || hasOperation(ABDOpcode, VT)) {
11170 EVT VT =
N->getValueType(0);
11205 EVT VT =
N->getValueType(0);
11228 auto *ShAmt = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
11230 if (ShAmt && ShAmt->getAPIntValue().ult(BW) &&
11231 ShAmt->getZExtValue() >= (BW / 2) &&
11232 (ShAmt->getZExtValue() % 16) == 0 && TLI.
isTypeLegal(HalfVT) &&
11234 (!LegalOperations || hasOperation(
ISD::BSWAP, HalfVT))) {
11236 if (
uint64_t NewShAmt = (ShAmt->getZExtValue() - (BW / 2)))
11251 auto *ShAmt = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
11252 if (ShAmt && ShAmt->getAPIntValue().ult(BW) &&
11253 ShAmt->getZExtValue() % 8 == 0) {
11268 EVT VT =
N->getValueType(0);
11296 EVT VT =
N->getValueType(0);
11313 EVT VT =
N->getValueType(0);
11325 EVT VT =
N->getValueType(0);
11342 EVT VT =
N->getValueType(0);
11354 EVT VT =
N->getValueType(0);
11366 const APInt &Amt = AmtC->getAPIntValue();
11367 if (Amt.
ult(NumBits)) {
11401 EVT VT =
LHS.getValueType();
11407 return (Flags.hasNoSignedZeros() ||
Options.NoSignedZerosFPMath) &&
11409 (Flags.hasNoNaNs() ||
11459 const unsigned Opcode =
N->getOpcode();
11465 unsigned FloorISD = 0;
11466 auto VT =
N->getValueType(0);
11467 bool IsUnsigned =
false;
11496 if (IsUnsigned && !
Add->getFlags().hasNoUnsignedWrap())
11499 if (!IsUnsigned && !
Add->getFlags().hasNoSignedWrap())
11502 return DAG.
getNode(FloorISD,
SDLoc(
N),
N->getValueType(0), {A, B});
11509 if ((LHS == True && RHS == False) || (LHS == False && RHS == True))
11515 True, DAG, LegalOperations, ForCodeSize);
11527 if (LHS == NegTrue) {
11531 RHS, DAG, LegalOperations, ForCodeSize);
11534 if (NegRHS == False) {
11536 False,
CC, TLI, DAG);
11556 EVT VT =
N->getValueType(0);
11558 VT !=
Cond.getOperand(0).getValueType())
11605 EVT VT =
N->getValueType(0);
11606 EVT CondVT =
Cond.getValueType();
11612 auto *C1 = dyn_cast<ConstantSDNode>(N1);
11613 auto *C2 = dyn_cast<ConstantSDNode>(N2);
11617 if (CondVT != MVT::i1 || LegalOperations) {
11632 C1->
isZero() && C2->isOne()) {
11647 assert(CondVT == MVT::i1 && !LegalOperations);
11650 if (C1->
isOne() && C2->isZero())
11658 if (C1->
isZero() && C2->isOne()) {
11665 if (C1->
isZero() && C2->isAllOnes()) {
11678 const APInt &C1Val = C1->getAPIntValue();
11679 const APInt &C2Val = C2->getAPIntValue();
11682 if (C1Val - 1 == C2Val) {
11688 if (C1Val + 1 == C2Val) {
11708 if (C2->isAllOnes()) {
11720template <
class MatchContextClass>
11724 N->getOpcode() == ISD::VP_SELECT) &&
11725 "Expected a (v)(vp.)select");
11727 SDValue T =
N->getOperand(1),
F =
N->getOperand(2);
11728 EVT VT =
N->getValueType(0);
11730 MatchContextClass matcher(DAG, TLI,
N);
11766 EVT VT =
N->getValueType(0);
11830 EVT VT =
LHS.getValueType();
11832 if (LegalOperations && !hasOperation(ABDOpc, VT))
11842 return DAG.
getNode(ABDOpc,
DL, VT, LHS, RHS);
11845 hasOperation(ABDOpc, VT))
11854 return DAG.
getNode(ABDOpc,
DL, VT, LHS, RHS);
11857 hasOperation(ABDOpc, VT))
11871 EVT VT =
N->getValueType(0);
11879 if (
SDValue V = foldBoolSelectToLogic<EmptyMatchContext>(
N,
DL, DAG))
11889 if (
SDValue V = foldSelectOfConstants(
N))
11893 if (SimplifySelectOps(
N, N1, N2))
11896 if (VT0 == MVT::i1) {
11905 bool normalizeToSequence =
11914 if (normalizeToSequence || !InnerSelect.
use_empty())
11916 InnerSelect, N2, Flags);
11919 recursivelyDeleteUnusedNodes(InnerSelect.
getNode());
11926 Cond1, N1, N2, Flags);
11927 if (normalizeToSequence || !InnerSelect.
use_empty())
11929 InnerSelect, Flags);
11932 recursivelyDeleteUnusedNodes(InnerSelect.
getNode());
11942 if (!normalizeToSequence) {
11948 if (
SDValue Combined = visitANDLike(N0, N1_0,
N)) {
11961 if (!normalizeToSequence) {
11967 if (
SDValue Combined = visitORLike(N0, N2_0,
DL))
12003 combineMinNumMaxNum(
DL, VT, Cond0, Cond1, N1, N2,
CC))
12014 auto *
C = dyn_cast<ConstantSDNode>(N2.
getOperand(1));
12015 auto *NotC = dyn_cast<ConstantSDNode>(Cond1);
12016 if (
C && NotC &&
C->getAPIntValue() == ~NotC->getAPIntValue()) {
12036 (!LegalOperations &&
12047 if (
SDValue ABD = foldSelectToABD(Cond0, Cond1, N1, N2,
CC,
DL))
12050 if (
SDValue NewSel = SimplifySelect(
DL, N0, N1, N2))
12055 if (
SDValue BinOp = foldSelectOfBinops(
N))
12071 EVT VT =
N->getValueType(0);
12079 if (
LHS->getNumOperands() != 2 ||
RHS->getNumOperands() != 2)
12088 for (
int i = 0; i < NumElems / 2; ++i) {
12089 if (
Cond->getOperand(i)->isUndef())
12092 if (BottomHalf ==
nullptr)
12093 BottomHalf = cast<ConstantSDNode>(
Cond.getOperand(i));
12094 else if (
Cond->getOperand(i).getNode() != BottomHalf)
12100 for (
int i = NumElems / 2; i < NumElems; ++i) {
12101 if (
Cond->getOperand(i)->isUndef())
12104 if (TopHalf ==
nullptr)
12105 TopHalf = cast<ConstantSDNode>(
Cond.getOperand(i));
12106 else if (
Cond->getOperand(i).getNode() != TopHalf)
12110 assert(TopHalf && BottomHalf &&
12111 "One half of the selector was all UNDEFs and the other was all the "
12112 "same value. This should have been addressed before this function.");
12115 BottomHalf->
isZero() ?
RHS->getOperand(0) :
LHS->getOperand(0),
12116 TopHalf->
isZero() ?
RHS->getOperand(1) :
LHS->getOperand(1));
12129 EVT VT = BasePtr.getValueType();
12133 SplatVal.getValueType() == VT) {
12139 if (Index.getOpcode() !=
ISD::ADD)
12145 Index = Index.getOperand(1);
12151 Index = Index.getOperand(0);
12166 Index = Index.getOperand(0);
12179 Index = Index.getOperand(0);
12264 MST1->isSimple() && MST1->getBasePtr() ==
Ptr &&
12267 MST1->getMemoryVT().getStoreSize()) ||
12271 CombineTo(MST1, MST1->getChain());
12288 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
12292 Value.getValueType().isInteger() &&
12293 (!isa<ConstantSDNode>(
Value) ||
12294 !cast<ConstantSDNode>(
Value)->isOpaque())) {
12295 APInt TruncDemandedBits =
12321 Value.getOperand(0).getValueType());
12332 auto *SST = cast<VPStridedStoreSDNode>(
N);
12335 if (
auto *CStride = dyn_cast<ConstantSDNode>(SST->getStride());
12336 CStride && CStride->getZExtValue() == EltVT.
getStoreSize()) {
12338 SST->getBasePtr(), SST->getOffset(), SST->getMask(),
12339 SST->getVectorLength(), SST->getMemoryVT(),
12340 SST->getMemOperand(), SST->getAddressingMode(),
12341 SST->isTruncatingStore(), SST->isCompressingStore());
12350 SDValue Passthru =
N->getOperand(2);
12353 bool HasPassthru = !Passthru.
isUndef();
12366 unsigned NumSelected = 0;
12368 for (
unsigned I = 0;
I < NumElmts; ++
I) {
12381 for (
unsigned Rest = NumSelected; Rest < NumElmts; ++Rest) {
12436 return CombineTo(
N, PassThru, MGT->
getChain());
12472 return CombineTo(
N, NewLd, NewLd.
getValue(1));
12476 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
12504 EVT DataVT =
Index.getValueType();
12512 auto *SLD = cast<VPStridedLoadSDNode>(
N);
12515 if (
auto *CStride = dyn_cast<ConstantSDNode>(SLD->getStride());
12516 CStride && CStride->getZExtValue() == EltVT.
getStoreSize()) {
12518 SLD->getAddressingMode(), SLD->getExtensionType(), SLD->getValueType(0),
12519 SDLoc(
N), SLD->getChain(), SLD->getBasePtr(), SLD->getOffset(),
12520 SLD->getMask(), SLD->getVectorLength(), SLD->getMemoryVT(),
12521 SLD->getMemOperand(), SLD->isExpandingLoad());
12522 return CombineTo(
N, NewLd, NewLd.
getValue(1));
12533 EVT VT =
N->getValueType(0);
12534 if (!
Cond.hasOneUse() ||
Cond.getScalarValueSizeInBits() != 1 ||
12543 bool AllAddOne =
true;
12544 bool AllSubOne =
true;
12546 for (
unsigned i = 0; i != Elts; ++i) {
12568 if (AllAddOne || AllSubOne) {
12604 if (
SDValue V = foldBoolSelectToLogic<VPMatchContext>(
N,
DL, DAG))
12614 EVT VT =
N->getValueType(0);
12620 if (
SDValue V = foldBoolSelectToLogic<EmptyMatchContext>(
N,
DL, DAG))
12646 bool isAbs =
false;
12665 AddToWorklist(Shift.
getNode());
12666 AddToWorklist(
Add.getNode());
12678 if (
SDValue FMinMax = combineMinNumMaxNum(
DL, VT, LHS, RHS, N1, N2,
CC))
12693 EVT NarrowVT =
LHS.getValueType();
12701 SetCCWidth != 1 && SetCCWidth < WideWidth &&
12717 if (
SDValue ABD = foldSelectToABD(LHS, RHS, N1, N2,
CC,
DL))
12747 (OpLHS == CondLHS || OpRHS == CondLHS))
12750 if (OpRHS.getOpcode() == CondRHS.getOpcode() &&
12753 CondLHS == OpLHS) {
12758 return Cond->getAPIntValue() ==
~Op->getAPIntValue();
12799 if (OpLHS == LHS) {
12815 return (!
Op && !
Cond) ||
12817 Cond->getAPIntValue() == (-
Op->getAPIntValue() - 1));
12848 if (SimplifySelectOps(
N, N1, N2))
12868 if (
SDValue V = foldVSelectOfConstants(
N))
12902 AddToWorklist(
SCC.getNode());
12906 if (
auto *SCCC = dyn_cast<ConstantSDNode>(
SCC.getNode()))
12907 return SCCC->isZero() ? N3 : N2;
12911 if (
SCC->isUndef())
12918 SCC.getOperand(1), N2, N3,
SCC.getOperand(2));
12925 if (SimplifySelectOps(
N, N2, N3))
12929 return SimplifySelectCC(
DL, N0, N1, N2, N3,
CC);
12937 N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BRCOND;
12940 EVT VT =
N->getValueType(0);
12941 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
12947 if (PreferSetCC && Combined.getOpcode() !=
ISD::SETCC) {
12948 SDValue NewSetCC = rebuildSetCC(Combined);
12976 A.getOperand(0) ==
B.getOperand(0);
12980 B.getOperand(0) ==
A;
12983 bool IsRotate =
false;
12986 if (IsAndWithShift(N0, N1)) {
12988 ShiftOrRotate = N1;
12989 }
else if (IsAndWithShift(N1, N0)) {
12991 ShiftOrRotate = N0;
12992 }
else if (IsRotateWithOp(N0, N1)) {
12995 ShiftOrRotate = N1;
12996 }
else if (IsRotateWithOp(N1, N0)) {
12999 ShiftOrRotate = N0;
13002 if (AndOrOp && ShiftOrRotate && ShiftOrRotate.hasOneUse() &&
13007 auto GetAPIntValue = [](
SDValue Op) -> std::optional<APInt> {
13010 if (CNode ==
nullptr)
13011 return std::nullopt;
13014 std::optional<APInt> AndCMask =
13015 IsRotate ? std::nullopt : GetAPIntValue(AndOrOp.
getOperand(1));
13016 std::optional<APInt> ShiftCAmt =
13017 GetAPIntValue(ShiftOrRotate.getOperand(1));
13021 if (ShiftCAmt && (IsRotate || AndCMask) && ShiftCAmt->ult(NumBits)) {
13022 unsigned ShiftOpc = ShiftOrRotate.getOpcode();
13024 bool CanTransform = IsRotate;
13025 if (!CanTransform) {
13027 CanTransform = *ShiftCAmt == (~*AndCMask).
popcount();
13029 CanTransform &= (*ShiftCAmt + AndCMask->popcount()) == NumBits;
13037 OpVT, ShiftOpc, ShiftCAmt->isPowerOf2(), *ShiftCAmt, AndCMask);
13039 if (CanTransform && NewShiftOpc != ShiftOpc) {
13041 DAG.
getNode(NewShiftOpc,
DL, OpVT, ShiftOrRotate.getOperand(0),
13042 ShiftOrRotate.getOperand(1));
13049 NumBits - ShiftCAmt->getZExtValue())
13050 :
APInt::getLowBitsSet(NumBits,
13051 NumBits - ShiftCAmt->getZExtValue());
13059 return DAG.
getSetCC(
DL, VT, NewAndOrOp, NewShiftOrRotate,
Cond);
13088 if (!
N.hasOneUse())
13091 if (!isa<LoadSDNode>(
N))
13117 unsigned Opcode =
N->getOpcode();
13119 EVT VT =
N->getValueType(0);
13122 "Expected EXTEND dag node in input!");
13163 unsigned Opcode =
N->getOpcode();
13165 EVT VT =
N->getValueType(0);
13168 "Expected EXTEND dag node in input!");
13173 if (isa<ConstantSDNode>(N0))
13174 return DAG.
getNode(Opcode,
DL, VT, N0);
13182 if (isa<ConstantSDNode>(Op1) && isa<ConstantSDNode>(Op2) &&
13193 unsigned FoldOpc = Opcode;
13216 for (
unsigned i = 0; i != NumElts; ++i) {
13218 if (
Op.isUndef()) {
13229 APInt C =
Op->getAsAPIntVal().zextOrTrunc(EVTBits);
13247 bool HasCopyToRegUses =
false;
13262 for (
unsigned i = 0; i != 2; ++i) {
13266 if (!isa<ConstantSDNode>(UseOp))
13280 HasCopyToRegUses =
true;
13283 if (HasCopyToRegUses) {
13284 bool BothLiveOut =
false;
13287 BothLiveOut =
true;
13294 return !ExtendNodes.
empty();
13304 for (
SDNode *SetCC : SetCCs) {
13307 for (
unsigned j = 0;
j != 2; ++
j) {
13309 if (SOp == OrigLoad)
13323 EVT DstVT =
N->getValueType(0);
13328 "Unexpected node type (not an extend)!");
13366 EVT SplitSrcVT = SrcVT;
13367 EVT SplitDstVT = DstVT;
13380 const unsigned NumSplits =
13387 for (
unsigned Idx = 0;
Idx < NumSplits;
Idx++) {
13406 AddToWorklist(NewChain.
getNode());
13408 CombineTo(
N, NewValue);
13414 ExtendSetCCUses(SetCCs, N0, NewValue, (
ISD::NodeType)
N->getOpcode());
13415 CombineTo(N0.
getNode(), Trunc, NewChain);
13423 EVT VT =
N->getValueType(0);
13424 EVT OrigVT =
N->getOperand(0).getValueType();
13446 EVT MemVT =
Load->getMemoryVT();
13467 Load->getChain(),
Load->getBasePtr(),
13468 Load->getMemoryVT(),
Load->getMemOperand());
13481 if (
SDValue(Load, 0).hasOneUse()) {
13485 Load->getValueType(0), ExtLoad);
13486 CombineTo(Load, Trunc, ExtLoad.
getValue(1));
13490 recursivelyDeleteUnusedNodes(N0.
getNode());
13499SDValue DAGCombiner::matchVSelectOpSizesWithSetCC(
SDNode *Cast) {
13500 unsigned CastOpcode = Cast->
getOpcode();
13504 "Unexpected opcode for vector select narrowing/widening");
13544 bool LegalOperations,
SDNode *
N,
13555 if ((LegalOperations || !LN0->
isSimple() ||
13566 Combiner.recursivelyDeleteUnusedNodes(LN0);
13579 bool NonNegZExt =
false) {
13586 "Unexpected load type or opcode");
13603 !cast<LoadSDNode>(N0)->isSimple()) &&
13607 bool DoXform =
true;
13620 Combiner.ExtendSetCCUses(SetCCs, N0, ExtLoad, ExtOpc);
13624 if (NoReplaceTrunc) {
13626 Combiner.recursivelyDeleteUnusedNodes(LN0);
13646 if ((LegalOperations || !cast<MaskedLoadSDNode>(N0)->
isSimple()) &&
13668 auto *ALoad = dyn_cast<AtomicSDNode>(N0);
13671 EVT MemoryVT = ALoad->getMemoryVT();
13680 EVT OrigVT = ALoad->getValueType(0);
13682 auto *NewALoad = cast<AtomicSDNode>(DAG.
getAtomic(
13684 ALoad->getBasePtr(), ALoad->getMemOperand()));
13685 NewALoad->setExtensionType(ExtLoadType);
13695 bool LegalOperations) {
13707 EVT VT =
N->getValueType(0);
13708 EVT XVT =
X.getValueType();
13724 return DAG.
getNode(ShiftOpcode,
DL, VT, NotX, ShiftAmount);
13738 EVT VT =
N->getValueType(0);
13748 if (VT.
isVector() && !LegalOperations &&
13767 if (SVT == MatchingVecType) {
13783 auto IsFreeToExtend = [&](
SDValue V) {
13791 cast<LoadSDNode>(V)->isSimple() &&
13805 if (
User->getOpcode() != ExtOpcode ||
User->getValueType(0) != VT)
13811 if (IsFreeToExtend(N00) && IsFreeToExtend(N01)) {
13831 SDValue ExtTrueVal = (SetCCWidth == 1)
13835 if (
SDValue SCC = SimplifySelectCC(
DL, N00, N01, ExtTrueVal, Zero,
CC,
true))
13847 return DAG.
getSelect(
DL, VT, SetCC, ExtTrueVal, Zero);
13856 EVT VT =
N->getValueType(0);
13860 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
13898 if (NarrowLoad.getNode() != N0.
getNode()) {
13899 CombineTo(N0.
getNode(), NarrowLoad);
13901 AddToWorklist(oye);
13909 unsigned OpBits =
Op.getScalarValueSizeInBits();
13915 if (OpBits == DestBits) {
13921 if (OpBits < DestBits) {
13930 Flags.setNoSignedWrap(
true);
13938 if (OpBits < DestBits)
13940 else if (OpBits > DestBits)
13960 if (
SDValue ExtLoad = CombineExtLoad(
N))
13995 bool NoReplaceTruncAnd = !N0.
hasOneUse();
13999 if (NoReplaceTruncAnd) {
14002 CombineTo(N0.
getNode(), TruncAnd);
14004 if (NoReplaceTrunc) {
14009 CombineTo(LN00, Trunc, ExtLoad.
getValue(1));
14028 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
14059 if (NewXor.getNode() == N0.
getNode()) {
14085 "Expected extend op");
14131 EVT VT =
N->getValueType(0);
14135 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
14166 APInt TruncatedBits =
14168 APInt(
Op.getScalarValueSizeInBits(), 0) :
14171 std::min(
Op.getScalarValueSizeInBits(),
14177 return ZExtOrTrunc;
14187 if (NarrowLoad.getNode() != N0.
getNode()) {
14188 CombineTo(N0.
getNode(), NarrowLoad);
14190 AddToWorklist(oye);
14198 if (
N->getFlags().hasNonNeg()) {
14206 if (OpBits == DestBits) {
14212 if (OpBits < DestBits) {
14222 Flags.setNoSignedWrap(
true);
14223 Flags.setNoUnsignedWrap(
true);
14235 AddToWorklist(
Op.getNode());
14239 return ZExtOrTrunc;
14245 AddToWorklist(
Op.getNode());
14281 if (
SDValue ExtLoad = CombineExtLoad(
N))
14301 bool DoXform =
true;
14305 auto *AndC = cast<ConstantSDNode>(N0.
getOperand(1));
14308 if (isAndLoadExtLoad(AndC, LN00, LoadResultTy, ExtVT))
14324 bool NoReplaceTruncAnd = !N0.
hasOneUse();
14328 if (NoReplaceTruncAnd) {
14331 CombineTo(N0.
getNode(), TruncAnd);
14333 if (NoReplaceTrunc) {
14338 CombineTo(LN00, Trunc, ExtLoad.
getValue(1));
14347 if (
SDValue ZExtLoad = CombineZExtLogicopShiftLoad(
N))
14363 if (!LegalOperations && VT.
isVector() &&
14395 if (
SDValue SCC = SimplifySelectCC(
14399 cast<CondCodeSDNode>(N0.
getOperand(2))->get(),
true))
14408 if (
auto *ShAmtC = dyn_cast<ConstantSDNode>(ShAmt)) {
14415 if (ShAmtC->getAPIntValue().ugt(KnownZeroBits)) {
14436 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
14460 EVT VT =
N->getValueType(0);
14494 if (NarrowLoad.getNode() != N0.
getNode()) {
14495 CombineTo(N0.
getNode(), NarrowLoad);
14497 AddToWorklist(oye);
14515 assert(isa<ConstantSDNode>(
Y) &&
"Expected constant to be folded!");
14531 bool DoXform =
true;
14544 CombineTo(
N, ExtLoad);
14545 if (NoReplaceTrunc) {
14547 recursivelyDeleteUnusedNodes(LN0);
14551 CombineTo(LN0, Trunc, ExtLoad.
getValue(1));
14565 if (!LegalOperations || TLI.
isLoadExtLegal(ExtType, VT, MemVT)) {
14569 CombineTo(
N, ExtLoad);
14571 recursivelyDeleteUnusedNodes(LN0);
14585 if (VT.
isVector() && !LegalOperations) {
14597 cast<CondCodeSDNode>(N0.
getOperand(2))->get());
14605 cast<CondCodeSDNode>(N0.
getOperand(2))->get());
14610 if (
SDValue SCC = SimplifySelectCC(
14613 cast<CondCodeSDNode>(N0.
getOperand(2))->get(),
true))
14627 unsigned Opcode =
N->getOpcode();
14630 EVT AssertVT = cast<VTSDNode>(N1)->getVT();
14634 AssertVT == cast<VTSDNode>(N0.
getOperand(1))->getVT())
14646 EVT BigA_AssertVT = cast<VTSDNode>(BigA.
getOperand(1))->getVT();
14647 EVT MinAssertVT = AssertVT.
bitsLT(BigA_AssertVT) ? AssertVT : BigA_AssertVT;
14661 EVT BigA_AssertVT = cast<VTSDNode>(BigA.
getOperand(1))->getVT();
14662 if (AssertVT.
bitsLT(BigA_AssertVT)) {
14676 Align AL = cast<AssertAlignSDNode>(
N)->getAlign();
14681 if (
auto *AAN = dyn_cast<AssertAlignSDNode>(N0))
14683 std::max(AL, AAN->getAlign()));
14693 unsigned AlignShift =
Log2(AL);
14698 if (LHSAlignShift >= AlignShift || RHSAlignShift >= AlignShift) {
14699 if (LHSAlignShift < AlignShift)
14701 if (RHSAlignShift < AlignShift)
14716 unsigned Opc =
N->getOpcode();
14720 EVT VT =
N->getValueType(0);
14730 unsigned ShAmt = 0;
14735 unsigned ShiftedOffset = 0;
14740 ExtVT = cast<VTSDNode>(
N->getOperand(1))->getVT();
14748 auto *LN = dyn_cast<LoadSDNode>(N0);
14749 auto *N1C = dyn_cast<ConstantSDNode>(
N->getOperand(1));
14755 uint64_t MemoryWidth = LN->getMemoryVT().getScalarSizeInBits();
14756 if (MemoryWidth <= ShAmt)
14767 LN->getExtensionType() != ExtType)
14771 auto AndC = dyn_cast<ConstantSDNode>(
N->getOperand(1));
14776 unsigned ActiveBits = 0;
14777 if (
Mask.isMask()) {
14778 ActiveBits =
Mask.countr_one();
14779 }
else if (
Mask.isShiftedMask(ShAmt, ActiveBits)) {
14780 ShiftedOffset = ShAmt;
14801 if (!
SRL.hasOneUse())
14806 auto *LN = dyn_cast<LoadSDNode>(
SRL.getOperand(0));
14807 auto *SRL1C = dyn_cast<ConstantSDNode>(
SRL.getOperand(1));
14814 ShAmt = SRL1C->getZExtValue();
14815 uint64_t MemoryWidth = LN->getMemoryVT().getSizeInBits();
14816 if (ShAmt >= MemoryWidth)
14843 isa<ConstantSDNode>(
Mask->getOperand(1))) {
14844 unsigned Offset, ActiveBits;
14845 const APInt& ShiftMask =
Mask->getConstantOperandAPInt(1);
14846 if (ShiftMask.
isMask()) {
14868 N0 =
SRL.getOperand(0);
14876 unsigned ShLeftAmt = 0;
14880 ShLeftAmt = N01->getZExtValue();
14886 if (!isa<LoadSDNode>(N0))
14893 !isLegalNarrowLdSt(LN0, ExtType, ExtVT, ShAmt))
14896 auto AdjustBigEndianShift = [&](
unsigned ShAmt) {
14897 unsigned LVTStoreBits =
14900 return LVTStoreBits - EVTStoreBits - ShAmt;
14905 unsigned PtrAdjustmentInBits =
14908 uint64_t PtrOff = PtrAdjustmentInBits / 8;
14914 AddToWorklist(NewPtr.
getNode());
14929 WorklistRemover DeadNodes(*
this);
14934 if (ShLeftAmt != 0) {
14946 if (ShiftedOffset != 0) {
14963 EVT VT =
N->getValueType(0);
14964 EVT ExtVT = cast<VTSDNode>(N1)->getVT();
14994 if ((N00Bits <= ExtVTBits ||
15010 if ((N00Bits == ExtVTBits ||
15011 (!IsZext && (N00Bits < ExtVTBits ||
15013 (!LegalOperations ||
15038 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
15045 if (
auto *ShAmt = dyn_cast<ConstantSDNode>(N0.
getOperand(1)))
15046 if (ShAmt->getAPIntValue().ule(VTBits - ExtVTBits)) {
15050 if (((VTBits - ExtVTBits) - ShAmt->getZExtValue()) < InSignBits)
15061 ExtVT == cast<LoadSDNode>(N0)->getMemoryVT() &&
15062 ((!LegalOperations && cast<LoadSDNode>(N0)->isSimple() &&
15065 auto *LN0 = cast<LoadSDNode>(N0);
15069 CombineTo(
N, ExtLoad);
15071 AddToWorklist(ExtLoad.
getNode());
15077 N0.
hasOneUse() && ExtVT == cast<LoadSDNode>(N0)->getMemoryVT() &&
15078 ((!LegalOperations && cast<LoadSDNode>(N0)->isSimple()) &&
15080 auto *LN0 = cast<LoadSDNode>(N0);
15084 CombineTo(
N, ExtLoad);
15092 if (ExtVT == Ld->getMemoryVT() && N0.
hasOneUse() &&
15096 VT,
DL, Ld->getChain(), Ld->getBasePtr(), Ld->getOffset(),
15097 Ld->getMask(), Ld->getPassThru(), ExtVT, Ld->getMemOperand(),
15098 Ld->getAddressingMode(),
ISD::SEXTLOAD, Ld->isExpandingLoad());
15099 CombineTo(
N, ExtMaskedLoad);
15106 if (
auto *GN0 = dyn_cast<MaskedGatherSDNode>(N0)) {
15107 if (
SDValue(GN0, 0).hasOneUse() && ExtVT == GN0->getMemoryVT() &&
15109 SDValue Ops[] = {GN0->getChain(), GN0->getPassThru(), GN0->getMask(),
15110 GN0->getBasePtr(), GN0->getIndex(), GN0->getScale()};
15113 DAG.
getVTList(VT, MVT::Other), ExtVT,
DL, Ops, GN0->getMemOperand(),
15116 CombineTo(
N, ExtLoad);
15118 AddToWorklist(ExtLoad.
getNode());
15141 (!LegalOperations ||
15155 bool LegalOperations) {
15156 unsigned InregOpcode =
N->getOpcode();
15160 EVT VT =
N->getValueType(0);
15162 Src.getValueType().getVectorElementType(),
15166 "Expected EXTEND_VECTOR_INREG dag node in input!");
15175 Src = Src.getOperand(0);
15176 if (Src.getValueType() != SrcVT)
15182 return DAG.
getNode(Opcode,
DL, VT, Src);
15187 EVT VT =
N->getValueType(0);
15212 EVT VT =
N->getValueType(0);
15233 unsigned NumSrcBits = In.getScalarValueSizeInBits();
15235 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
15256 unsigned NumSrcBits = In.getScalarValueSizeInBits();
15258 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
15279 unsigned NumSrcBits = In.getScalarValueSizeInBits();
15281 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
15304 auto AllowedTruncateSat = [&](
unsigned Opc,
EVT SrcVT,
EVT VT) ->
bool {
15316 }
else if (Src.getOpcode() ==
ISD::UMIN) {
15330 EVT VT =
N->getValueType(0);
15345 return SaturatedTR;
15372 EVT ExtVT = cast<VTSDNode>(ExtVal)->getVT();
15393 if (LegalTypes && !LegalOperations && VT.
isScalarInteger() && VT != MVT::i1 &&
15395 EVT TrTy =
N->getValueType(0);
15400 if (Src.getOpcode() ==
ISD::SRL && Src.getOperand(0)->hasOneUse()) {
15403 Src = Src.getOperand(0);
15410 EVT VecTy = Src.getOperand(0).getValueType();
15411 EVT ExTy = Src.getValueType();
15415 auto NewEltCnt = EltCnt * SizeRatio;
15420 SDValue EltNo = Src->getOperand(1);
15421 if (isa<ConstantSDNode>(EltNo) &&
isTypeLegal(NVT)) {
15423 int Index = isLE ? (Elt * SizeRatio + EltOffset)
15424 : (Elt * SizeRatio + (SizeRatio - 1) - EltOffset);
15435 if (!LegalOperations ||
15458 AddToWorklist(Amt.
getNode());
15507 if (BuildVectEltTy == TruncVecEltTy) {
15511 unsigned TruncEltOffset = BuildVecNumElts / TruncVecNumElts;
15512 unsigned FirstElt = isLE ? 0 : (TruncEltOffset - 1);
15514 assert((BuildVecNumElts % TruncVecNumElts) == 0 &&
15515 "Invalid number of elements");
15518 for (
unsigned i = FirstElt, e = BuildVecNumElts; i <
e;
15519 i += TruncEltOffset)
15529 if (
SDValue Reduced = reduceLoadWidth(
N))
15535 auto *LN0 = cast<LoadSDNode>(N0);
15552 unsigned NumDefs = 0;
15556 if (!
X.isUndef()) {
15567 X.getValueType().getVectorElementCount()));
15573 if (NumDefs == 1) {
15574 assert(
V.getNode() &&
"The single defined operand is empty!");
15576 for (
unsigned i = 0, e = VTs.
size(); i != e; ++i) {
15582 AddToWorklist(
NV.getNode());
15597 (!LegalOperations ||
15625 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
15639 if (!LegalOperations && N0.
hasOneUse() &&
15672 if (!LegalOperations && N0.
hasOneUse() &&
15708 !LD1->hasOneUse() || !LD2->hasOneUse() ||
15709 LD1->getAddressSpace() != LD2->getAddressSpace())
15712 unsigned LD1Fast = 0;
15713 EVT LD1VT = LD1->getValueType(0);
15718 *LD1->getMemOperand(), &LD1Fast) && LD1Fast)
15719 return DAG.
getLoad(VT,
SDLoc(
N), LD1->getChain(), LD1->getBasePtr(),
15720 LD1->getPointerInfo(), LD1->getAlign());
15735 EVT VT =
N->getValueType(0);
15772 auto IsBitCastOrFree = [&TLI, FPOpcode](
SDValue Op,
EVT VT) {
15786 IsBitCastOrFree(LogicOp0, VT)) {
15789 NumFPLogicOpsConv++;
15800 EVT VT =
N->getValueType(0);
15816 cast<BuildVectorSDNode>(N0)->isConstant())
15817 return ConstantFoldBITCASTofBUILD_VECTOR(N0.
getNode(),
15825 if (!LegalOperations ||
15831 if (
C.getNode() !=
N)
15844 auto IsFreeBitcast = [VT](
SDValue V) {
15846 V.getOperand(0).getValueType() == VT) ||
15867 ((!LegalOperations && cast<LoadSDNode>(N0)->isSimple()) ||
15881 if (
SDValue V = foldBitcastedFPLogic(
N, DAG, TLI))
15901 AddToWorklist(NewConv.
getNode());
15904 if (N0.
getValueType() == MVT::ppcf128 && !LegalTypes) {
15911 AddToWorklist(FlipBit.
getNode());
15918 AddToWorklist(
Hi.getNode());
15920 AddToWorklist(FlipBit.
getNode());
15924 AddToWorklist(FlipBits.
getNode());
15954 AddToWorklist(
X.getNode());
15958 if (OrigXWidth < VTWidth) {
15960 AddToWorklist(
X.getNode());
15961 }
else if (OrigXWidth > VTWidth) {
15966 X.getValueType(),
X,
15968 X.getValueType()));
15969 AddToWorklist(
X.getNode());
15971 AddToWorklist(
X.getNode());
15974 if (N0.
getValueType() == MVT::ppcf128 && !LegalTypes) {
15977 AddToWorklist(Cst.
getNode());
15979 AddToWorklist(
X.getNode());
15981 AddToWorklist(XorResult.
getNode());
15985 SDLoc(XorResult)));
15986 AddToWorklist(XorResult64.
getNode());
15990 AddToWorklist(FlipBit.
getNode());
15993 AddToWorklist(FlipBits.
getNode());
15999 AddToWorklist(
X.getNode());
16004 AddToWorklist(Cst.
getNode());
16012 if (
SDValue CombineLD = CombineConsecutiveLoads(N0.
getNode(), VT))
16035 auto PeekThroughBitcast = [&](
SDValue Op) {
16037 Op.getOperand(0).getValueType() == VT)
16056 for (
int i = 0; i != MaskScale; ++i)
16057 NewMask.
push_back(M < 0 ? -1 : M * MaskScale + i);
16062 return LegalShuffle;
16069 EVT VT =
N->getValueType(0);
16070 return CombineConsecutiveLoads(
N, VT);
16097 bool AllowMultipleMaybePoisonOperands =
16131 bool HadMaybePoisonOperands = !MaybePoisonOperands.
empty();
16132 bool IsNewMaybePoisonOperand = MaybePoisonOperands.
insert(
Op).second;
16133 if (IsNewMaybePoisonOperand)
16134 MaybePoisonOperandNumbers.
push_back(OpNo);
16135 if (!HadMaybePoisonOperands)
16137 if (IsNewMaybePoisonOperand && !AllowMultipleMaybePoisonOperands) {
16146 for (
unsigned OpNo : MaybePoisonOperandNumbers) {
16157 SDValue MaybePoisonOperand =
N->getOperand(0).getOperand(OpNo);
16166 FrozenMaybePoisonOperand.
getOperand(0) == FrozenMaybePoisonOperand) {
16170 MaybePoisonOperand);
16180 N0 =
N->getOperand(0);
16192 if (
auto *SVN = dyn_cast<ShuffleVectorSDNode>(N0)) {
16201 "Can't create node that may be undef/poison!");
16208ConstantFoldBITCASTofBUILD_VECTOR(
SDNode *BV,
EVT DstEltVT) {
16212 if (SrcEltVT == DstEltVT)
return SDValue(BV, 0);
16219 if (SrcBitSize == DstBitSize) {
16224 if (
Op.getValueType() != SrcEltVT)
16227 AddToWorklist(Ops.
back().getNode());
16241 BV = ConstantFoldBITCASTofBUILD_VECTOR(BV, IntVT).getNode();
16249 SDNode *Tmp = ConstantFoldBITCASTofBUILD_VECTOR(BV, TmpVT).getNode();
16252 return ConstantFoldBITCASTofBUILD_VECTOR(Tmp, DstEltVT);
16260 auto *BVN = cast<BuildVectorSDNode>(BV);
16266 if (!BVN->getConstantRawBits(IsLE, DstBitSize, RawBits, UndefElements))
16271 for (
unsigned I = 0, E = RawBits.
size();
I != E; ++
I) {
16272 if (UndefElements[
I])
16288 N->getFlags().hasAllowContract();
16293 return Options.NoInfsFPMath ||
N->getFlags().hasNoInfs();
16297template <
class MatchContextClass>
16301 EVT VT =
N->getValueType(0);
16303 MatchContextClass matcher(DAG, TLI,
N);
16306 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
16311 bool HasFMAD = !UseVP && (LegalOperations && TLI.
isFMADLegal(DAG,
N));
16315 (!LegalOperations || matcher.isOperationLegalOrCustom(
ISD::FMA, VT)) &&
16319 if (!HasFMAD && !HasFMA)
16323 Options.UnsafeFPMath || HasFMAD);
16325 if (!AllowFusionGlobally && !
N->getFlags().hasAllowContract())
16351 return AllowFusionGlobally ||
N->getFlags().hasAllowContract();
16362 return matcher.getNode(PreferredFusedOpcode, SL, VT, N0.
getOperand(0),
16369 return matcher.getNode(PreferredFusedOpcode, SL, VT, N1.
getOperand(0),
16381 bool CanReassociate =
16382 Options.UnsafeFPMath ||
N->getFlags().hasAllowReassociation();
16383 if (CanReassociate) {
16388 }
else if (isFusedOp(N1) && N1.
hasOneUse()) {
16394 while (E && isFusedOp(TmpFMA) && TmpFMA.
hasOneUse()) {
16419 PreferredFusedOpcode, SL, VT,
16433 PreferredFusedOpcode, SL, VT,
16445 return matcher.getNode(
16446 PreferredFusedOpcode, SL, VT,
X,
Y,
16447 matcher.getNode(PreferredFusedOpcode, SL, VT,
16451 if (isFusedOp(N0)) {
16472 return matcher.getNode(
16473 PreferredFusedOpcode, SL, VT,
16476 matcher.getNode(PreferredFusedOpcode, SL, VT,
16482 if (isFusedOp(N00)) {
16496 if (isFusedOp(N1)) {
16517 if (isFusedOp(N10)) {
16534template <
class MatchContextClass>
16538 EVT VT =
N->getValueType(0);
16540 MatchContextClass matcher(DAG, TLI,
N);
16543 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
16548 bool HasFMAD = !UseVP && (LegalOperations && TLI.
isFMADLegal(DAG,
N));
16552 (!LegalOperations || matcher.isOperationLegalOrCustom(
ISD::FMA, VT)) &&
16556 if (!HasFMAD && !HasFMA)
16561 Options.UnsafeFPMath || HasFMAD);
16564 if (!AllowFusionGlobally && !
N->getFlags().hasAllowContract())
16573 bool NoSignedZero =
Options.NoSignedZerosFPMath ||
Flags.hasNoSignedZeros();
16580 return AllowFusionGlobally ||
N->getFlags().hasAllowContract();
16586 return matcher.getNode(PreferredFusedOpcode, SL, VT, XY.
getOperand(0),
16597 return matcher.getNode(
16598 PreferredFusedOpcode, SL, VT,
16599 matcher.getNode(
ISD::FNEG, SL, VT, YZ.getOperand(0)),
16600 YZ.getOperand(1),
X);
16610 if (
SDValue V = tryToFoldXSubYZ(N0, N1))
16613 if (
SDValue V = tryToFoldXYSubZ(N0, N1))
16617 if (
SDValue V = tryToFoldXYSubZ(N0, N1))
16620 if (
SDValue V = tryToFoldXSubYZ(N0, N1))
16629 return matcher.
getNode(PreferredFusedOpcode, SL, VT,
16630 matcher.getNode(
ISD::FNEG, SL, VT, N00), N01,
16631 matcher.getNode(
ISD::FNEG, SL, VT, N1));
16644 PreferredFusedOpcode, SL, VT,
16647 matcher.getNode(
ISD::FNEG, SL, VT, N1));
16660 PreferredFusedOpcode, SL, VT,
16684 PreferredFusedOpcode, SL, VT,
16708 PreferredFusedOpcode, SL, VT,
16717 return Options.UnsafeFPMath ||
N->getFlags().hasAllowReassociation();
16731 bool CanFuse =
Options.UnsafeFPMath ||
N->getFlags().hasAllowContract();
16734 if (CanFuse && isFusedOp(N0) &&
16735 isContractableAndReassociableFMUL(N0.
getOperand(2)) &&
16737 return matcher.getNode(
16739 matcher.
getNode(PreferredFusedOpcode, SL, VT,
16747 if (CanFuse && isFusedOp(N1) &&
16748 isContractableAndReassociableFMUL(N1.
getOperand(2)) &&
16753 PreferredFusedOpcode, SL, VT,
16756 matcher.
getNode(PreferredFusedOpcode, SL, VT,
16757 matcher.getNode(
ISD::FNEG, SL, VT, N20), N21, N0));
16762 if (isFusedOp(N0) && N0->
hasOneUse()) {
16766 if (isContractableAndReassociableFMUL(N020) &&
16772 PreferredFusedOpcode, SL, VT,
16775 matcher.getNode(
ISD::FNEG, SL, VT, N1)));
16788 if (isFusedOp(N00)) {
16790 if (isContractableAndReassociableFMUL(N002) &&
16794 PreferredFusedOpcode, SL, VT,
16798 PreferredFusedOpcode, SL, VT,
16801 matcher.getNode(
ISD::FNEG, SL, VT, N1)));
16811 if (isContractableAndReassociableFMUL(N120) &&
16817 PreferredFusedOpcode, SL, VT,
16821 PreferredFusedOpcode, SL, VT,
16839 if (isContractableAndReassociableFMUL(N102) &&
16845 PreferredFusedOpcode, SL, VT,
16850 PreferredFusedOpcode, SL, VT,
16864SDValue DAGCombiner::visitFMULForFMADistributiveCombine(
SDNode *
N) {
16867 EVT VT =
N->getValueType(0);
16888 bool HasFMAD =
Options.UnsafeFPMath &&
16892 if (!HasFMAD && !HasFMA)
16904 if (
C->isExactlyValue(+1.0))
16905 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
16907 if (
C->isExactlyValue(-1.0))
16908 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
16915 if (
SDValue FMA = FuseFADD(N0, N1))
16917 if (
SDValue FMA = FuseFADD(N1, N0))
16927 if (C0->isExactlyValue(+1.0))
16928 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
16931 if (C0->isExactlyValue(-1.0))
16932 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
16937 if (C1->isExactlyValue(+1.0))
16938 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
16940 if (C1->isExactlyValue(-1.0))
16941 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
16948 if (
SDValue FMA = FuseFSUB(N0, N1))
16950 if (
SDValue FMA = FuseFSUB(N1, N0))
16960 if (
SDValue Fused = visitFADDForFMACombine<VPMatchContext>(
N)) {
16962 AddToWorklist(Fused.getNode());
16973 EVT VT =
N->getValueType(0);
16987 if (N0CFP && !N1CFP)
16992 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
16997 if (N1C && N1C->
isZero())
17001 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17007 N1, DAG, LegalOperations, ForCodeSize))
17013 N0, DAG, LegalOperations, ForCodeSize))
17020 return C &&
C->isExactlyValue(-2.0);
17024 if (isFMulNegTwo(N0)) {
17030 if (isFMulNegTwo(N1)) {
17041 if ((
Options.NoNaNsFPMath ||
Flags.hasNoNaNs()) && AllowNewConst) {
17055 (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros())) &&
17073 if (CFP01 && !CFP00 && N0.
getOperand(0) == N1) {
17094 if (CFP11 && !CFP10 && N1.
getOperand(0) == N0) {
17142 VT, N0, N1, Flags))
17147 if (
SDValue Fused = visitFADDForFMACombine<EmptyMatchContext>(
N)) {
17149 AddToWorklist(Fused.getNode());
17159 EVT VT =
N->getValueType(0);
17160 EVT ChainVT =
N->getValueType(1);
17167 N1, DAG, LegalOperations, ForCodeSize)) {
17169 {Chain, N0, NegN1});
17175 N0, DAG, LegalOperations, ForCodeSize)) {
17177 {Chain, N1, NegN0});
17187 EVT VT =
N->getValueType(0);
17202 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
17205 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17209 if (N1CFP && N1CFP->
isZero()) {
17211 Flags.hasNoSignedZeros()) {
17223 if (N0CFP && N0CFP->
isZero()) {
17225 (
Options.NoSignedZerosFPMath ||
Flags.hasNoSignedZeros())) {
17242 (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros())) &&
17258 if (
SDValue Fused = visitFSUBForFMACombine<EmptyMatchContext>(
N)) {
17259 AddToWorklist(Fused.getNode());
17282 EVT VT =
N->getValueType(0);
17285 std::optional<int> Mantissa;
17286 auto GetConstAndPow2Ops = [&](
unsigned ConstOpIdx) {
17287 if (ConstOpIdx == 1 &&
N->getOpcode() ==
ISD::FDIV)
17291 Pow2Op =
N->getOperand(1 - ConstOpIdx);
17304 if (CFP ==
nullptr)
17307 const APFloat &APF = CFP->getValueAPF();
17315 int CurExp =
ilogb(APF);
17318 N->getOpcode() ==
ISD::FMUL ? CurExp : (CurExp - MaxExpChange);
17321 N->getOpcode() ==
ISD::FDIV ? CurExp : (CurExp + MaxExpChange);
17329 Mantissa = ThisMantissa;
17331 return *Mantissa == ThisMantissa && ThisMantissa > 0;
17338 if (!GetConstAndPow2Ops(0) && !GetConstAndPow2Ops(1))
17367 NewIntVT, DAG.
getBitcast(NewIntVT, ConstOp), Shift);
17376 EVT VT =
N->getValueType(0);
17396 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
17399 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17402 if (
Options.UnsafeFPMath ||
Flags.hasAllowReassociation()) {
17428 VT, N0, N1, Flags))
17462 if (
Flags.hasNoNaNs() &&
Flags.hasNoSignedZeros() &&
17470 auto TrueOpnd = dyn_cast<ConstantFPSDNode>(
Select.getOperand(1));
17471 auto FalseOpnd = dyn_cast<ConstantFPSDNode>(
Select.getOperand(2));
17473 if (TrueOpnd && FalseOpnd &&
17475 isa<ConstantFPSDNode>(
Cond.getOperand(1)) &&
17476 cast<ConstantFPSDNode>(
Cond.getOperand(1))->isExactlyValue(0.0)) {
17494 if (TrueOpnd->isExactlyValue(-1.0) && FalseOpnd->isExactlyValue(1.0) &&
17498 if (TrueOpnd->isExactlyValue(1.0) && FalseOpnd->isExactlyValue(-1.0))
17507 if (
SDValue Fused = visitFMULForFMADistributiveCombine(
N)) {
17508 AddToWorklist(Fused.getNode());
17514 if (
SDValue R = combineFMulOrFDivWithIntPow2(
N))
17520template <
class MatchContextClass>
SDValue DAGCombiner::visitFMA(
SDNode *
N) {
17526 EVT VT =
N->getValueType(0);
17531 MatchContextClass matcher(DAG, TLI,
N);
17556 if (N0CFP && N0CFP->
isZero())
17558 if (N1CFP && N1CFP->
isZero())
17566 return matcher.getNode(
ISD::FADD,
DL, VT, N0, N2);
17571 return matcher.getNode(
ISD::FMA,
DL, VT, N1, N0, N2);
17573 bool CanReassociate =
17574 Options.UnsafeFPMath ||
N->getFlags().hasAllowReassociation();
17575 if (CanReassociate) {
17580 return matcher.getNode(
17589 return matcher.getNode(
17599 return matcher.getNode(
ISD::FADD,
DL, VT, N0, N2);
17604 AddToWorklist(RHSNeg.
getNode());
17605 return matcher.getNode(
ISD::FADD,
DL, VT, N2, RHSNeg);
17619 if (CanReassociate) {
17621 if (N1CFP && N0 == N2) {
17639 SDValue(
N, 0), DAG, LegalOperations, ForCodeSize))
17648 EVT VT =
N->getValueType(0);
17671 if (LegalDAG || (!UnsafeMath && !
Flags.hasAllowReciprocal()))
17675 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
17686 unsigned NumElts = 1;
17687 EVT VT =
N->getValueType(0);
17691 if (!MinUses || (N1->
use_size() * NumElts) < MinUses)
17697 for (
auto *U : N1->
users()) {
17698 if (
U->getOpcode() ==
ISD::FDIV &&
U->getOperand(1) == N1) {
17700 if (
U->getOperand(1).getOpcode() ==
ISD::FSQRT &&
17701 U->getOperand(0) ==
U->getOperand(1).getOperand(0) &&
17702 U->getFlags().hasAllowReassociation() &&
17703 U->getFlags().hasNoSignedZeros())
17708 if (UnsafeMath ||
U->getFlags().hasAllowReciprocal())
17715 if ((
Users.size() * NumElts) < MinUses)
17723 for (
auto *U :
Users) {
17724 SDValue Dividend =
U->getOperand(0);
17725 if (Dividend != FPOne) {
17727 Reciprocal, Flags);
17728 CombineTo(U, NewNode);
17729 }
else if (U != Reciprocal.
getNode()) {
17732 CombineTo(U, Reciprocal);
17741 EVT VT =
N->getValueType(0);
17756 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
17759 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17776 (
Options.UnsafeFPMath ||
Flags.hasAllowReciprocal()))) &&
17777 (!LegalOperations ||
17787 if (
Options.UnsafeFPMath ||
Flags.hasAllowReciprocal()) {
17827 A =
Y.getOperand(0);
17836 if (
SDValue Rsqrt = buildRsqrtEstimate(AAZ, Flags))
17840 recursivelyDeleteUnusedNodes(AAZ.
getNode());
17848 AddToWorklist(Div.
getNode());
17856 if (
SDValue RV = BuildDivEstimate(N0, N1, Flags))
17861 if ((
Options.NoSignedZerosFPMath ||
Flags.hasNoSignedZeros()) &&
17862 (
Options.UnsafeFPMath ||
Flags.hasAllowReassociation()))
17882 if (
SDValue R = combineFMulOrFDivWithIntPow2(
N))
17891 EVT VT =
N->getValueType(0);
17903 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17913 bool NeedsCopySign =
17937 if (!
Flags.hasApproximateFuncs() ||
17950 return buildSqrtEstimate(N0, Flags);
17965 if (YTy == MVT::f128)
17984 EVT VT =
N->getValueType(0);
17995 if (!
V.isNegative()) {
18049 EVT VT =
N->getValueType(0);
18059 if (!
Flags.hasNoSignedZeros() || !
Flags.hasNoInfs() || !
Flags.hasNoNaNs() ||
18060 !
Flags.hasApproximateFuncs())
18079 if (ExponentIs025 || ExponentIs075) {
18090 if ((!
Flags.hasNoSignedZeros() && ExponentIs025) || !
Flags.hasNoInfs() ||
18091 !
Flags.hasApproximateFuncs())
18124 EVT VT =
N->getValueType(0);
18145 EVT VT =
N->getValueType(0);
18193 EVT VT =
N->getValueType(0);
18231 EVT VT =
N->getValueType(0);
18237 EVT SrcVT = Src.getValueType();
18252 unsigned ActualSize = std::min(InputSize, OutputSize);
18261 return DAG.
getNode(ExtOp,
DL, VT, Src);
18272 EVT VT =
N->getValueType(0);
18288 EVT VT =
N->getValueType(0);
18304 EVT VT =
N->getValueType(0);
18323 EVT VT =
N->getValueType(0);
18336 const bool NIsTrunc =
N->getConstantOperandVal(1) == 1;
18374 AddToWorklist(Tmp.
getNode());
18378 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
18386 EVT VT =
N->getValueType(0);
18390 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
18410 if (
In.getValueType() == VT)
return In;
18424 CombineTo(
N, ExtLoad);
18433 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
18441 EVT VT =
N->getValueType(0);
18452 EVT VT =
N->getValueType(0);
18486 EVT VT =
N->getValueType(0);
18497 EVT VT =
N->getValueType(0);
18514 N->getFlags().hasNoSignedZeros()) && N0.
hasOneUse()) {
18519 if (
SDValue Cast = foldSignChangeInBitcast(
N))
18528 EVT VT =
N->getValueType(0);
18530 unsigned Opc =
N->getOpcode();
18552 return PropagatesNaN ?
N->getOperand(1) :
N->getOperand(0);
18561 if (IsMin == AF.
isNegative() && (!PropagatesNaN ||
Flags.hasNoNaNs()))
18562 return N->getOperand(1);
18568 if (IsMin != AF.
isNegative() && (PropagatesNaN ||
Flags.hasNoNaNs()))
18569 return N->getOperand(0);
18573 if (
SDValue SD = reassociateReduction(
18577 Opc,
SDLoc(
N), VT, N0, N1, Flags))
18585 EVT VT =
N->getValueType(0);
18594 return N->getOperand(0);
18601 if (
SDValue Cast = foldSignChangeInBitcast(
N))
18634 bool Updated =
false;
18646 return True || False;
18650 if (!IsAlwaysTrueOrFalse(
Cond, S1C)) {
18657 S1 =
S1->getOperand(0);
18689 if (
SDValue NewN1 = rebuildSetCC(N1))
18691 ChainHandle.getValue(), NewN1, N2,
N->getFlags());
18700 (
N.getOperand(0).hasOneUse() &&
18701 N.getOperand(0).getOpcode() ==
ISD::SRL))) {
18704 N =
N.getOperand(0);
18753 SDValue Tmp = visitXOR(
N.getNode());
18760 N = XORHandle.getValue();
18772 bool Equal =
false;
18777 Op0 =
N->getOperand(0);
18778 Op1 =
N->getOperand(1);
18782 EVT SetCCVT =
N.getValueType();
18802 SDValue CondLHS =
N->getOperand(2), CondRHS =
N->getOperand(3);
18812 CondLHS, CondRHS,
CC->get(),
SDLoc(
N),
18830 if (LD->isIndexed())
18832 EVT VT = LD->getMemoryVT();
18835 Ptr = LD->getBasePtr();
18836 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
18837 if (ST->isIndexed())
18839 EVT VT = ST->getMemoryVT();
18842 Ptr = ST->getBasePtr();
18845 if (LD->isIndexed())
18847 EVT VT = LD->getMemoryVT();
18851 Ptr = LD->getBasePtr();
18854 if (ST->isIndexed())
18856 EVT VT = ST->getMemoryVT();
18860 Ptr = ST->getBasePtr();
18874bool DAGCombiner::CombineToPreIndexedLoadStore(
SDNode *
N) {
18878 bool IsLoad =
true;
18879 bool IsMasked =
false;
18901 bool Swapped =
false;
18902 if (isa<ConstantSDNode>(BasePtr)) {
18921 if (isa<FrameIndexSDNode>(BasePtr) || isa<RegisterSDNode>(BasePtr))
18926 SDValue Val = IsMasked ? cast<MaskedStoreSDNode>(
N)->getValue()
18927 : cast<StoreSDNode>(
N)->getValue();
18930 if (Val == BasePtr)
18948 if (isa<ConstantSDNode>(
Offset))
18966 if (!isa<ConstantSDNode>(Op1)) {
18984 bool RealUse =
false;
19020 WorklistRemover DeadNodes(*
this);
19029 deleteAndRecombine(
N);
19035 for (
unsigned i = 0, e = OtherUses.
size(); i != e; ++i) {
19036 unsigned OffsetIdx = 1;
19037 if (OtherUses[i]->getOperand(OffsetIdx).
getNode() ==
BasePtr.getNode())
19040 BasePtr.getNode() &&
"Expected BasePtr operand");
19053 auto *CN = cast<ConstantSDNode>(OtherUses[i]->getOperand(OffsetIdx));
19054 const APInt &Offset0 = CN->getAPIntValue();
19056 int X0 = (OtherUses[i]->getOpcode() ==
ISD::SUB && OffsetIdx == 1) ? -1 : 1;
19057 int Y0 = (OtherUses[i]->getOpcode() ==
ISD::SUB && OffsetIdx == 0) ? -1 : 1;
19063 APInt CNV = Offset0;
19064 if (X0 < 0) CNV = -CNV;
19065 if (X1 * Y0 * Y1 < 0) CNV = CNV + Offset1;
19066 else CNV = CNV - Offset1;
19078 deleteAndRecombine(OtherUses[i]);
19083 deleteAndRecombine(
Ptr.getNode());
19084 AddToWorklist(
Result.getNode());
19105 if (isa<FrameIndexSDNode>(BasePtr) || isa<RegisterSDNode>(BasePtr))
19115 if (isa<MemSDNode>(
User)) {
19116 bool IsLoad =
true;
19117 bool IsMasked =
false;
19120 IsMasked, OtherPtr, TLI)) {
19146 IsMasked,
Ptr, TLI) ||
19180bool DAGCombiner::CombineToPostIndexedLoadStore(
SDNode *
N) {
19184 bool IsLoad =
true;
19185 bool IsMasked =
false;
19206 ++PostIndexedNodes;
19210 WorklistRemover DeadNodes(*
this);
19219 deleteAndRecombine(
N);
19223 Result.getValue(IsLoad ? 1 : 0));
19224 deleteAndRecombine(
Op);
19239 !cast<ConstantSDNode>(Inc)->isOpaque()) &&
19240 "Cannot split out indexing using opaque target constants");
19258 EVT STMemType =
ST->getMemoryVT();
19259 if (STType == STMemType)
19281 EVT LDMemType =
LD->getMemoryVT();
19282 EVT LDType =
LD->getValueType(0);
19284 "Attempting to extend value of non-matching type");
19285 if (LDType == LDMemType)
19288 switch (
LD->getExtensionType()) {
19324 if (!BasePtrST.equalBaseIndex(BasePtrLD, DAG,
Offset))
19327 GatherAllAliases(Store, Chain, Aliases);
19328 if (Aliases.
empty() ||
19329 (Aliases.
size() == 1 && Aliases.
front().getNode() == Store))
19338 if (BasePtrST.equalBaseIndex(BasePtrLD, DAG,
Offset))
19354 if (!ST || !
ST->isSimple() ||
ST->getAddressSpace() !=
LD->getAddressSpace())
19357 EVT LDType =
LD->getValueType(0);
19358 EVT LDMemType =
LD->getMemoryVT();
19359 EVT STMemType =
ST->getMemoryVT();
19360 EVT STType =
ST->getValue().getValueType();
19384 int64_t OrigOffset =
Offset;
19397 STCoversLD = (
Offset == 0) && LdMemSize == StMemSize;
19403 if (
LD->isIndexed()) {
19410 return CombineTo(LD, Ops, 3);
19412 return CombineTo(LD, Val, Chain);
19419 if (
Offset == 0 && LDType == STType && STMemType == LDMemType) {
19422 return ReplaceLd(LD,
ST->getValue(), Chain);
19430 SDLoc(ST), STType);
19432 return ReplaceLd(LD, Val, Chain);
19450 if (
LD->getBasePtr().isUndef() ||
Offset != 0)
19455 if (!getTruncatedStoreValue(ST, Val))
19459 if (STMemType != LDMemType) {
19467 if (!extendLoadedValueToExtension(LD, Val))
19469 return ReplaceLd(LD, Val, Chain);
19474 deleteAndRecombine(Val.
getNode());
19487 if (
LD->isSimple()) {
19488 if (
N->getValueType(1) == MVT::Other) {
19490 if (!
N->hasAnyUseOfValue(0)) {
19498 dbgs() <<
"\nWith chain: "; Chain.
dump(&DAG);
19500 WorklistRemover DeadNodes(*
this);
19502 AddUsersToWorklist(Chain.
getNode());
19503 if (
N->use_empty())
19504 deleteAndRecombine(
N);
19510 assert(
N->getValueType(2) == MVT::Other &&
"Malformed indexed loads?");
19518 if (!
N->hasAnyUseOfValue(0) && (CanSplitIdx || !
N->hasAnyUseOfValue(1))) {
19521 if (
N->hasAnyUseOfValue(1) && CanSplitIdx) {
19522 Index = SplitIndexingFromLoad(LD);
19525 AddUsersToWorklist(
N);
19529 dbgs() <<
"\nWith: ";
Undef.dump(&DAG);
19530 dbgs() <<
" and 2 other values\n");
19531 WorklistRemover DeadNodes(*
this);
19535 deleteAndRecombine(
N);
19543 if (
auto V = ForwardStoreValueToDirectLoad(LD))
19550 if (*Alignment >
LD->getAlign() &&
19551 isAligned(*Alignment,
LD->getSrcValueOffset())) {
19553 LD->getExtensionType(),
SDLoc(
N),
LD->getValueType(0), Chain,
Ptr,
19554 LD->getPointerInfo(),
LD->getMemoryVT(), *Alignment,
19555 LD->getMemOperand()->getFlags(),
LD->getAAInfo());
19563 if (
LD->isUnindexed()) {
19565 SDValue BetterChain = FindBetterChain(LD, Chain);
19568 if (Chain != BetterChain) {
19574 BetterChain,
Ptr,
LD->getMemOperand());
19577 LD->getValueType(0),
19578 BetterChain,
Ptr,
LD->getMemoryVT(),
19579 LD->getMemOperand());
19584 MVT::Other, Chain, ReplLoad.
getValue(1));
19587 return CombineTo(
N, ReplLoad.
getValue(0), Token);
19592 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
19597 if (SliceUpLoad(
N))
19617struct LoadedSlice {
19621 bool ForCodeSize =
false;
19624 unsigned Loads = 0;
19625 unsigned Truncates = 0;
19626 unsigned CrossRegisterBanksCopies = 0;
19627 unsigned ZExts = 0;
19628 unsigned Shift = 0;
19630 explicit Cost(
bool ForCodeSize) : ForCodeSize(ForCodeSize) {}
19633 Cost(
const LoadedSlice &LS,
bool ForCodeSize)
19634 : ForCodeSize(ForCodeSize), Loads(1) {
19635 EVT TruncType =
LS.Inst->getValueType(0);
19636 EVT LoadedType =
LS.getLoadedType();
19637 if (TruncType != LoadedType &&
19638 !
LS.DAG->getTargetLoweringInfo().isZExtFree(LoadedType, TruncType))
19646 void addSliceGain(
const LoadedSlice &LS) {
19655 if (
LS.canMergeExpensiveCrossRegisterBankCopy())
19656 ++CrossRegisterBanksCopies;
19660 Loads +=
RHS.Loads;
19661 Truncates +=
RHS.Truncates;
19662 CrossRegisterBanksCopies +=
RHS.CrossRegisterBanksCopies;
19663 ZExts +=
RHS.ZExts;
19664 Shift +=
RHS.Shift;
19669 return Loads ==
RHS.Loads && Truncates ==
RHS.Truncates &&
19670 CrossRegisterBanksCopies ==
RHS.CrossRegisterBanksCopies &&
19671 ZExts ==
RHS.ZExts && Shift ==
RHS.Shift;
19679 unsigned ExpensiveOpsLHS = Loads + CrossRegisterBanksCopies;
19680 unsigned ExpensiveOpsRHS =
RHS.Loads +
RHS.CrossRegisterBanksCopies;
19683 if (!ForCodeSize && ExpensiveOpsLHS != ExpensiveOpsRHS)
19684 return ExpensiveOpsLHS < ExpensiveOpsRHS;
19685 return (Truncates + ZExts + Shift + ExpensiveOpsLHS) <
19686 (
RHS.Truncates +
RHS.ZExts +
RHS.Shift + ExpensiveOpsRHS);
19712 : Inst(Inst), Origin(Origin), Shift(Shift), DAG(DAG) {}
19717 APInt getUsedBits()
const {
19722 assert(Origin &&
"No original load to compare against.");
19724 assert(Inst &&
"This slice is not bound to an instruction");
19726 "Extracted slice is bigger than the whole type!");
19728 UsedBits.setAllBits();
19729 UsedBits = UsedBits.zext(
BitWidth);
19730 UsedBits <<= Shift;
19735 unsigned getLoadedSize()
const {
19736 unsigned SliceSize = getUsedBits().popcount();
19737 assert(!(SliceSize & 0x7) &&
"Size is not a multiple of a byte.");
19738 return SliceSize / 8;
19743 EVT getLoadedType()
const {
19744 assert(DAG &&
"Missing context");
19759 bool isLegal()
const {
19761 if (!Origin || !Inst || !DAG)
19771 EVT SliceType = getLoadedType();
19782 if (PtrType == MVT::Untyped || PtrType.
isExtended())
19795 if (TruncateType != SliceType &&
19805 uint64_t getOffsetFromBase()
const {
19806 assert(DAG &&
"Missing context.");
19808 assert(!(Shift & 0x7) &&
"Shifts not aligned on Bytes are not supported.");
19812 "The size of the original loaded type is not a multiple of a"
19817 "Invalid shift amount for given loaded size");
19830 assert(Inst && Origin &&
"Unable to replace a non-existing slice.");
19834 int64_t
Offset =
static_cast<int64_t
>(getOffsetFromBase());
19835 assert(
Offset >= 0 &&
"Offset too big to fit in int64_t!");
19845 EVT SliceType = getLoadedType();
19855 if (SliceType != FinalType)
19865 bool canMergeExpensiveCrossRegisterBankCopy()
const {
19871 assert(DAG &&
"Missing context");
19873 EVT ResVT =
User->getValueType(0);
19887 if (!
TRI ||
TRI->getCommonSubClass(ArgRC, ResRC))
19892 unsigned IsFast = 0;
19933 const LoadedSlice &Second) {
19935 "Unable to match different memory origins.");
19937 assert((UsedBits & Second.getUsedBits()) == 0 &&
19938 "Slices are not supposed to overlap.");
19939 UsedBits |= Second.getUsedBits();
19948 LoadedSlice::Cost &GlobalLSCost) {
19949 unsigned NumberOfSlices = LoadedSlices.
size();
19951 if (NumberOfSlices < 2)
19956 llvm::sort(LoadedSlices, [](
const LoadedSlice &
LHS,
const LoadedSlice &
RHS) {
19957 assert(
LHS.Origin ==
RHS.Origin &&
"Different bases not implemented.");
19958 return LHS.getOffsetFromBase() <
RHS.getOffsetFromBase();
19960 const TargetLowering &TLI = LoadedSlices[0].DAG->getTargetLoweringInfo();
19963 const LoadedSlice *
First =
nullptr;
19964 const LoadedSlice *Second =
nullptr;
19965 for (
unsigned CurrSlice = 0; CurrSlice < NumberOfSlices; ++CurrSlice,
19968 Second = &LoadedSlices[CurrSlice];
19975 EVT LoadedType =
First->getLoadedType();
19978 if (LoadedType != Second->getLoadedType())
19982 Align RequiredAlignment;
19983 if (!TLI.hasPairedLoad(LoadedType, RequiredAlignment)) {
19989 if (
First->getAlign() < RequiredAlignment)
19996 assert(GlobalLSCost.Loads > 0 &&
"We save more loads than we created!");
19997 --GlobalLSCost.Loads;
20014 const APInt &UsedBits,
bool ForCodeSize) {
20015 unsigned NumberOfSlices = LoadedSlices.
size();
20017 return NumberOfSlices > 1;
20020 if (NumberOfSlices != 2)
20028 LoadedSlice::Cost OrigCost(ForCodeSize), GlobalSlicingCost(ForCodeSize);
20030 OrigCost.Loads = 1;
20031 for (
unsigned CurrSlice = 0; CurrSlice < NumberOfSlices; ++CurrSlice) {
20032 const LoadedSlice &LS = LoadedSlices[CurrSlice];
20034 LoadedSlice::Cost SliceCost(LS, ForCodeSize);
20035 GlobalSlicingCost += SliceCost;
20039 OrigCost.addSliceGain(LS);
20044 return OrigCost > GlobalSlicingCost;
20053bool DAGCombiner::SliceUpLoad(
SDNode *
N) {
20059 !
LD->getValueType(0).isInteger())
20065 if (
LD->getValueType(0).isScalableVector())
20070 APInt UsedBits(
LD->getValueSizeInBits(0), 0);
20077 for (
SDUse &U :
LD->uses()) {
20079 if (
U.getResNo() != 0)
20083 unsigned Shift = 0;
20088 Shift =
User->getConstantOperandVal(1);
20101 unsigned Width =
User->getValueSizeInBits(0);
20106 LoadedSlice
LS(
User, LD, Shift, &DAG);
20107 APInt CurrentUsedBits =
LS.getUsedBits();
20110 if ((CurrentUsedBits & UsedBits) != 0)
20113 UsedBits |= CurrentUsedBits;
20134 for (
const LoadedSlice &LS : LoadedSlices) {
20136 CombineTo(
LS.Inst, SliceInst,
true);
20140 "It takes more than a zext to get to the loaded slice!!");
20147 AddToWorklist(Chain.
getNode());
20154static std::pair<unsigned, unsigned>
20156 std::pair<unsigned, unsigned> Result(0, 0);
20160 !isa<ConstantSDNode>(V->getOperand(1)) ||
20165 LoadSDNode *LD = cast<LoadSDNode>(V->getOperand(0));
20166 if (LD->getBasePtr() !=
Ptr)
return Result;
20169 if (V.getValueType() != MVT::i16 &&
20170 V.getValueType() != MVT::i32 &&
20171 V.getValueType() != MVT::i64)
20177 uint64_t NotMask = ~cast<ConstantSDNode>(V->getOperand(1))->getSExtValue();
20179 if (NotMaskLZ & 7)
return Result;
20181 if (NotMaskTZ & 7)
return Result;
20182 if (NotMaskLZ == 64)
return Result;
20189 if (V.getValueType() != MVT::i64 && NotMaskLZ)
20190 NotMaskLZ -= 64-V.getValueSizeInBits();
20192 unsigned MaskedBytes = (V.getValueSizeInBits()-NotMaskLZ-NotMaskTZ)/8;
20193 switch (MaskedBytes) {
20197 default:
return Result;
20202 if (NotMaskTZ && NotMaskTZ/8 % MaskedBytes)
return Result;
20211 if (!LD->isOperandOf(Chain.
getNode()))
20216 Result.first = MaskedBytes;
20217 Result.second = NotMaskTZ/8;
20228 unsigned NumBytes = MaskInfo.first;
20229 unsigned ByteShift = MaskInfo.second;
20235 ByteShift*8, (ByteShift+NumBytes)*8);
20244 bool UseTruncStore;
20245 if (DC->isTypeLegal(VT))
20246 UseTruncStore =
false;
20249 UseTruncStore =
true;
20275 StOffset = ByteShift;
20306 if (!
ST->isSimple())
20314 if (
ST->isTruncatingStore() || VT.
isVector())
20317 unsigned Opc =
Value.getOpcode();
20329 std::pair<unsigned, unsigned> MaskedLoad;
20331 if (MaskedLoad.first)
20333 Value.getOperand(1), ST,
this))
20338 if (MaskedLoad.first)
20340 Value.getOperand(0), ST,
this))
20354 if (
LD->getBasePtr() !=
Ptr ||
20355 LD->getPointerInfo().getAddrSpace() !=
20356 ST->getPointerInfo().getAddrSpace())
20365 if (Imm == 0 ||
Imm.isAllOnes())
20370 unsigned BitsPerByteMask = 7u;
20371 unsigned LSB =
Imm.countr_zero() & ~BitsPerByteMask;
20372 unsigned MSB = (
Imm.getActiveBits() - 1) | BitsPerByteMask;
20400 unsigned ShAmt = 0;
20402 for (; ShAmt + NewBW <= VTStoreSize; ShAmt += 8) {
20406 if (ShAmt + NewBW < MSB)
20411 ? VTStoreSize - NewBW - ShAmt
20413 PtrOff = PtrAdjustmentInBits / 8;
20416 unsigned IsFast = 0;
20419 LD->getAddressSpace(), NewAlign,
20420 LD->getMemOperand()->getFlags(), &IsFast) &&
20425 if (ShAmt + NewBW > VTStoreSize)
20428 APInt NewImm =
Imm.lshr(ShAmt).trunc(NewBW);
20436 LD->getPointerInfo().getWithOffset(PtrOff), NewAlign,
20437 LD->getMemOperand()->getFlags(),
LD->getAAInfo());
20442 ST->getPointerInfo().getWithOffset(PtrOff), NewAlign);
20444 AddToWorklist(NewPtr.
getNode());
20445 AddToWorklist(NewLD.
getNode());
20446 AddToWorklist(NewVal.
getNode());
20447 WorklistRemover DeadNodes(*
this);
20465 EVT VT =
LD->getMemoryVT();
20467 LD->isNonTemporal() ||
ST->isNonTemporal() ||
20468 LD->getPointerInfo().getAddrSpace() != 0 ||
20469 ST->getPointerInfo().getAddrSpace() != 0)
20479 unsigned FastLD = 0, FastST = 0;
20486 *
LD->getMemOperand(), &FastLD) ||
20488 *
ST->getMemOperand(), &FastST) ||
20489 !FastLD || !FastST)
20493 LD->getBasePtr(),
LD->getMemOperand());
20496 ST->getBasePtr(),
ST->getMemOperand());
20498 AddToWorklist(NewLD.
getNode());
20499 AddToWorklist(NewST.
getNode());
20500 WorklistRemover DeadNodes(*
this);
20522bool DAGCombiner::isMulAddWithConstProfitable(
SDNode *MulNode,
SDValue AddNode,
20534 if (
User == MulNode)
20557 if (OtherOp == MulVar)
20585 unsigned NumStores) {
20588 SDLoc StoreDL(StoreNodes[0].MemNode);
20590 for (
unsigned i = 0; i < NumStores; ++i) {
20591 Visited.
insert(StoreNodes[i].MemNode);
20595 for (
unsigned i = 0; i < NumStores; ++i) {
20596 if (Visited.
insert(StoreNodes[i].MemNode->getChain().getNode()).second)
20597 Chains.
push_back(StoreNodes[i].MemNode->getChain());
20600 assert(!Chains.
empty() &&
"Chain should have generated a chain");
20605 const Value *UnderlyingObj =
nullptr;
20606 for (
const auto &
MemOp : StoreNodes) {
20618 if (UnderlyingObj && UnderlyingObj != Obj)
20621 if (!UnderlyingObj)
20622 UnderlyingObj = Obj;
20628bool DAGCombiner::mergeStoresOfConstantsOrVecElts(
20630 bool IsConstantSrc,
bool UseVector,
bool UseTrunc) {
20635 assert((!UseTrunc || !UseVector) &&
20636 "This optimization cannot emit a vector truncating store");
20639 SDLoc DL(StoreNodes[0].MemNode);
20642 unsigned SizeInBits = NumStores * ElementSizeBits;
20645 std::optional<MachineMemOperand::Flags>
Flags;
20647 for (
unsigned I = 0;
I != NumStores; ++
I) {
20648 StoreSDNode *St = cast<StoreSDNode>(StoreNodes[
I].MemNode);
20663 unsigned Elts = NumStores * NumMemElts;
20671 if (IsConstantSrc) {
20673 for (
unsigned I = 0;
I != NumStores; ++
I) {
20674 StoreSDNode *St = cast<StoreSDNode>(StoreNodes[
I].MemNode);
20682 auto *
C = dyn_cast<ConstantSDNode>(Val);
20692 .zextOrTrunc(ElementSizeBits),
20702 DL, StoreTy, BuildVector);
20705 for (
unsigned i = 0; i < NumStores; ++i) {
20706 StoreSDNode *St = cast<StoreSDNode>(StoreNodes[i].MemNode);
20743 assert(IsConstantSrc &&
"Merged vector elements should use vector store");
20745 APInt StoreInt(SizeInBits, 0);
20750 for (
unsigned i = 0; i < NumStores; ++i) {
20751 unsigned Idx = IsLE ? (NumStores - 1 - i) : i;
20754 SDValue Val = St->getValue();
20756 StoreInt <<= ElementSizeBits;
20758 StoreInt |=
C->getAPIntValue()
20759 .zextOrTrunc(ElementSizeBits)
20760 .zextOrTrunc(SizeInBits);
20762 StoreInt |=
C->getValueAPF()
20764 .zextOrTrunc(ElementSizeBits)
20765 .zextOrTrunc(SizeInBits);
20783 SDValue NewChain = getMergeStoreChains(StoreNodes, NumStores);
20784 bool CanReusePtrInfo = hasSameUnderlyingObj(StoreNodes);
20798 FirstInChain->
getAlign(), *Flags, AAInfo);
20800 EVT LegalizedStoredValTy =
20802 unsigned LegalizedStoreSize = LegalizedStoredValTy.
getSizeInBits();
20805 DAG.
getConstant(
C->getAPIntValue().zextOrTrunc(LegalizedStoreSize),
DL,
20806 LegalizedStoredValTy);
20808 NewChain,
DL, ExtendedStoreVal, FirstInChain->
getBasePtr(),
20817 for (
unsigned i = 0; i < NumStores; ++i)
20818 CombineTo(StoreNodes[i].MemNode, NewStore);
20820 AddToWorklist(NewChain.
getNode());
20825DAGCombiner::getStoreMergeCandidates(
StoreSDNode *St,
20831 if (!
BasePtr.getBase().getNode() ||
BasePtr.getBase().isUndef())
20835 StoreSource StoreSrc = getStoreSource(Val);
20836 assert(StoreSrc != StoreSource::Unknown &&
"Expected known source for store");
20842 if (StoreSrc == StoreSource::Load) {
20843 auto *Ld = cast<LoadSDNode>(Val);
20845 LoadVT = Ld->getMemoryVT();
20847 if (MemVT != LoadVT)
20850 if (!Ld->hasNUsesOfValue(1, 0))
20854 if (!Ld->isSimple() || Ld->isIndexed())
20858 int64_t &
Offset) ->
bool {
20861 if (!
Other->isSimple() ||
Other->isIndexed())
20871 :
Other->getMemoryVT() != MemVT;
20872 switch (StoreSrc) {
20873 case StoreSource::Load: {
20877 auto *OtherLd = dyn_cast<LoadSDNode>(OtherBC);
20881 if (LoadVT != OtherLd->getMemoryVT())
20884 if (!OtherLd->hasNUsesOfValue(1, 0))
20888 if (!OtherLd->isSimple() || OtherLd->isIndexed())
20891 if (cast<LoadSDNode>(Val)->isNonTemporal() != OtherLd->isNonTemporal())
20896 if (!(LBasePtr.equalBaseIndex(LPtr, DAG)))
20900 case StoreSource::Constant:
20903 if (getStoreSource(OtherBC) != StoreSource::Constant)
20906 case StoreSource::Extract:
20908 if (
Other->isTruncatingStore())
20941 if (ChainsWithoutMergeableStores.
contains(RootNode))
20946 auto OverLimitInDependenceCheck = [&](
SDNode *StoreNode,
20947 SDNode *RootNode) ->
bool {
20948 auto RootCount = StoreRootCountMap.
find(StoreNode);
20949 return RootCount != StoreRootCountMap.
end() &&
20950 RootCount->second.first == RootNode &&
20954 auto TryToAddCandidate = [&](
SDUse &
Use) {
20958 if (
auto *OtherStore = dyn_cast<StoreSDNode>(
Use.
getUser())) {
20961 if (CandidateMatch(OtherStore,
Ptr, PtrDiff) &&
20962 !OverLimitInDependenceCheck(OtherStore, RootNode))
20963 StoreNodes.
push_back(MemOpLink(OtherStore, PtrDiff));
20967 unsigned NumNodesExplored = 0;
20968 const unsigned MaxSearchNodes = 1024;
20969 if (
auto *Ldn = dyn_cast<LoadSDNode>(RootNode)) {
20970 RootNode = Ldn->getChain().getNode();
20972 if (ChainsWithoutMergeableStores.
contains(RootNode))
20975 I != E && NumNodesExplored < MaxSearchNodes; ++
I, ++NumNodesExplored) {
20977 if (
I->getOperandNo() == 0 && isa<LoadSDNode>(
User)) {
20979 TryToAddCandidate(U2);
20982 if (
I->getOperandNo() == 0 && isa<StoreSDNode>(
User)) {
20983 TryToAddCandidate(*
I);
20988 I != E && NumNodesExplored < MaxSearchNodes; ++
I, ++NumNodesExplored)
20989 TryToAddCandidate(*
I);
20998bool DAGCombiner::checkMergeStoreCandidatesForDependencies(
21014 while (!Worklist.
empty()) {
21016 if (!Visited.
insert(
N).second)
21025 unsigned int Max = 1024 + Visited.
size();
21027 for (
unsigned i = 0; i < NumStores; ++i) {
21028 SDNode *
N = StoreNodes[i].MemNode;
21049 for (
unsigned i = 0; i < NumStores; ++i)
21055 if (Visited.
size() >= Max) {
21056 auto &RootCount = StoreRootCountMap[StoreNodes[i].MemNode];
21057 if (RootCount.first == RootNode)
21058 RootCount.second++;
21060 RootCount = {RootNode, 1};
21069 int64_t ElementSizeBytes)
const {
21072 size_t StartIdx = 0;
21073 while ((StartIdx + 1 < StoreNodes.
size()) &&
21074 StoreNodes[StartIdx].OffsetFromBase + ElementSizeBytes !=
21075 StoreNodes[StartIdx + 1].OffsetFromBase)
21079 if (StartIdx + 1 >= StoreNodes.
size())
21088 unsigned NumConsecutiveStores = 1;
21089 int64_t StartAddress = StoreNodes[0].OffsetFromBase;
21092 for (
unsigned i = 1, e = StoreNodes.
size(); i < e; ++i) {
21093 int64_t CurrAddress = StoreNodes[i].OffsetFromBase;
21094 if (CurrAddress - StartAddress != (ElementSizeBytes * i))
21096 NumConsecutiveStores = i + 1;
21098 if (NumConsecutiveStores > 1)
21099 return NumConsecutiveStores;
21107bool DAGCombiner::tryStoreMergeOfConstants(
21109 EVT MemVT,
SDNode *RootNode,
bool AllowVectors) {
21114 bool MadeChange =
false;
21117 while (NumConsecutiveStores >= 2) {
21121 unsigned LastLegalType = 1;
21122 unsigned LastLegalVectorType = 1;
21123 bool LastIntegerTrunc =
false;
21124 bool NonZero =
false;
21125 unsigned FirstZeroAfterNonZero = NumConsecutiveStores;
21126 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
21127 StoreSDNode *
ST = cast<StoreSDNode>(StoreNodes[i].MemNode);
21129 bool IsElementZero =
false;
21131 IsElementZero =
C->isZero();
21133 IsElementZero =
C->getConstantFPValue()->isNullValue();
21135 IsElementZero =
true;
21136 if (IsElementZero) {
21137 if (NonZero && FirstZeroAfterNonZero == NumConsecutiveStores)
21138 FirstZeroAfterNonZero = i;
21140 NonZero |= !IsElementZero;
21143 unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
21145 unsigned IsFast = 0;
21157 LastIntegerTrunc =
false;
21158 LastLegalType = i + 1;
21162 EVT LegalizedStoredValTy =
21170 LastIntegerTrunc =
true;
21171 LastLegalType = i + 1;
21180 unsigned Elts = (i + 1) * NumMemElts;
21187 LastLegalVectorType = i + 1;
21191 bool UseVector = (LastLegalVectorType > LastLegalType) && AllowVectors;
21192 unsigned NumElem = (UseVector) ? LastLegalVectorType : LastLegalType;
21193 bool UseTrunc = LastIntegerTrunc && !UseVector;
21205 unsigned NumSkip = 1;
21206 while ((NumSkip < NumConsecutiveStores) &&
21207 (NumSkip < FirstZeroAfterNonZero) &&
21208 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
21212 NumConsecutiveStores -= NumSkip;
21217 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
21220 NumConsecutiveStores -= NumElem;
21224 MadeChange |= mergeStoresOfConstantsOrVecElts(StoreNodes, MemVT, NumElem,
21226 UseVector, UseTrunc);
21230 NumConsecutiveStores -= NumElem;
21235bool DAGCombiner::tryStoreMergeOfExtracts(
21241 bool MadeChange =
false;
21244 while (NumConsecutiveStores >= 2) {
21248 unsigned NumStoresToMerge = 1;
21249 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
21251 unsigned Elts = (i + 1) * NumMemElts;
21253 unsigned IsFast = 0;
21264 NumStoresToMerge = i + 1;
21269 if (NumStoresToMerge < 2) {
21276 unsigned NumSkip = 1;
21277 while ((NumSkip < NumConsecutiveStores) &&
21278 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
21282 NumConsecutiveStores -= NumSkip;
21287 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumStoresToMerge,
21290 StoreNodes.
begin() + NumStoresToMerge);
21291 NumConsecutiveStores -= NumStoresToMerge;
21295 MadeChange |= mergeStoresOfConstantsOrVecElts(
21296 StoreNodes, MemVT, NumStoresToMerge,
false,
21299 StoreNodes.
erase(StoreNodes.
begin(), StoreNodes.
begin() + NumStoresToMerge);
21300 NumConsecutiveStores -= NumStoresToMerge;
21306 unsigned NumConsecutiveStores,
EVT MemVT,
21307 SDNode *RootNode,
bool AllowVectors,
21308 bool IsNonTemporalStore,
21309 bool IsNonTemporalLoad) {
21314 bool MadeChange =
false;
21323 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
21324 StoreSDNode *St = cast<StoreSDNode>(StoreNodes[i].MemNode);
21330 int64_t LdOffset = 0;
21331 if (LdBasePtr.
getBase().getNode()) {
21333 if (!LdBasePtr.equalBaseIndex(LdPtr, DAG, LdOffset))
21341 LoadNodes.
push_back(MemOpLink(Ld, LdOffset));
21344 while (NumConsecutiveStores >= 2 && LoadNodes.
size() >= 2) {
21345 Align RequiredAlignment;
21346 bool NeedRotate =
false;
21347 if (LoadNodes.
size() == 2) {
21351 StoreNodes[0].MemNode->getAlign() >= RequiredAlignment) {
21357 int64_t Offset0 = LoadNodes[0].OffsetFromBase;
21358 int64_t Offset1 = LoadNodes[1].OffsetFromBase;
21360 if (Offset0 - Offset1 == ElementSizeBytes &&
21370 LoadSDNode *FirstLoad = cast<LoadSDNode>(LoadNodes[0].MemNode);
21376 unsigned LastConsecutiveLoad = 1;
21379 unsigned LastLegalVectorType = 1;
21380 unsigned LastLegalIntegerType = 1;
21381 bool isDereferenceable =
true;
21382 bool DoIntegerTruncate =
false;
21383 int64_t StartAddress = LoadNodes[0].OffsetFromBase;
21385 for (
unsigned i = 1; i < LoadNodes.
size(); ++i) {
21387 if (LoadNodes[i].MemNode->getChain() != LoadChain)
21390 int64_t CurrAddress = LoadNodes[i].OffsetFromBase;
21391 if (CurrAddress - StartAddress != (ElementSizeBytes * i))
21393 LastConsecutiveLoad = i;
21395 if (isDereferenceable && !LoadNodes[i].MemNode->isDereferenceable())
21396 isDereferenceable =
false;
21399 unsigned Elts = (i + 1) * NumMemElts;
21406 unsigned IsFastSt = 0;
21407 unsigned IsFastLd = 0;
21421 LastLegalVectorType = i + 1;
21425 unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
21436 LastLegalIntegerType = i + 1;
21437 DoIntegerTruncate =
false;
21454 LastLegalIntegerType = i + 1;
21455 DoIntegerTruncate =
true;
21463 LastLegalVectorType > LastLegalIntegerType && AllowVectors;
21464 unsigned LastLegalType =
21465 std::max(LastLegalVectorType, LastLegalIntegerType);
21469 unsigned NumElem = std::min(NumConsecutiveStores, LastConsecutiveLoad + 1);
21470 NumElem = std::min(LastLegalType, NumElem);
21481 unsigned NumSkip = 1;
21482 while ((NumSkip < LoadNodes.
size()) &&
21483 (LoadNodes[NumSkip].MemNode->getAlign() <= FirstLoadAlign) &&
21484 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
21488 NumConsecutiveStores -= NumSkip;
21493 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
21497 NumConsecutiveStores -= NumElem;
21506 unsigned Elts = NumElem * NumMemElts;
21509 unsigned SizeInBits = NumElem * ElementSizeBytes * 8;
21513 SDLoc LoadDL(LoadNodes[0].MemNode);
21514 SDLoc StoreDL(StoreNodes[0].MemNode);
21519 SDValue NewStoreChain = getMergeStoreChains(StoreNodes, NumElem);
21520 bool CanReusePtrInfo = hasSameUnderlyingObj(StoreNodes);
21521 AddToWorklist(NewStoreChain.
getNode());
21526 if (IsNonTemporalLoad)
21538 if (UseVectorTy || !DoIntegerTruncate) {
21544 unsigned LoadWidth = ElementSizeBytes * 8 * 2;
21546 "Unexpected type for rotate-able load pair");
21553 NewStoreChain, StoreDL, StoreOp, FirstInChain->
getBasePtr(),
21556 FirstStoreAlign, StMMOFlags);
21563 FirstLoadAlign, LdMMOFlags);
21565 NewStoreChain, StoreDL, NewLoad, FirstInChain->
getBasePtr(),
21568 JointMemOpVT, FirstInChain->
getAlign(),
21573 for (
unsigned i = 0; i < NumElem; ++i) {
21574 LoadSDNode *Ld = cast<LoadSDNode>(LoadNodes[i].MemNode);
21581 for (
unsigned i = 0; i < NumElem; ++i) {
21582 SDValue Val = StoreNodes[i].MemNode->getOperand(1);
21583 CombineTo(StoreNodes[i].MemNode, NewStore);
21585 recursivelyDeleteUnusedNodes(Val.
getNode());
21591 NumConsecutiveStores -= NumElem;
21596bool DAGCombiner::mergeConsecutiveStores(
StoreSDNode *St) {
21612 if (ElementSizeBytes * 8 != (int64_t)MemVT.
getSizeInBits())
21618 const StoreSource StoreSrc = getStoreSource(StoredVal);
21619 if (StoreSrc == StoreSource::Unknown)
21624 SDNode *RootNode = getStoreMergeCandidates(St, StoreNodes);
21627 if (StoreNodes.
size() < 2)
21632 llvm::sort(StoreNodes, [](MemOpLink LHS, MemOpLink RHS) {
21633 return LHS.OffsetFromBase <
RHS.OffsetFromBase;
21637 Attribute::NoImplicitFloat);
21639 bool IsNonTemporalLoad = StoreSrc == StoreSource::Load &&
21640 cast<LoadSDNode>(StoredVal)->isNonTemporal();
21649 bool MadeChange =
false;
21650 while (StoreNodes.
size() > 1) {
21651 unsigned NumConsecutiveStores =
21652 getConsecutiveStores(StoreNodes, ElementSizeBytes);
21654 if (NumConsecutiveStores == 0)
21658 assert(NumConsecutiveStores >= 2 &&
"Expected at least 2 stores");
21659 switch (StoreSrc) {
21660 case StoreSource::Constant:
21661 MadeChange |= tryStoreMergeOfConstants(StoreNodes, NumConsecutiveStores,
21662 MemVT, RootNode, AllowVectors);
21665 case StoreSource::Extract:
21666 MadeChange |= tryStoreMergeOfExtracts(StoreNodes, NumConsecutiveStores,
21670 case StoreSource::Load:
21671 MadeChange |= tryStoreMergeOfLoads(StoreNodes, NumConsecutiveStores,
21672 MemVT, RootNode, AllowVectors,
21673 IsNonTemporalStore, IsNonTemporalLoad);
21683 ChainsWithoutMergeableStores.
insert(RootNode);
21693 if (
ST->isTruncatingStore()) {
21695 ST->getBasePtr(),
ST->getMemoryVT(),
21696 ST->getMemOperand());
21698 ReplStore = DAG.
getStore(BetterChain, SL,
ST->getValue(),
ST->getBasePtr(),
21699 ST->getMemOperand());
21704 MVT::Other,
ST->getChain(), ReplStore);
21707 AddToWorklist(Token.
getNode());
21710 return CombineTo(ST, Token,
false);
21744 if ((
isTypeLegal(MVT::i32) && !LegalOperations &&
ST->isSimple()) ||
21747 bitcastToAPInt().getZExtValue(),
SDLoc(CFP),
21754 if ((TLI.
isTypeLegal(MVT::i64) && !LegalOperations &&
21758 getZExtValue(),
SDLoc(CFP), MVT::i64);
21760 Ptr,
ST->getMemOperand());
21778 ST->getOriginalAlign(), MMOFlags, AAInfo);
21781 ST->getPointerInfo().getWithOffset(4),
21782 ST->getOriginalAlign(), MMOFlags, AAInfo);
21811 EltVT !=
Value.getOperand(0).getValueType().getVectorElementType())
21814 auto *Ld = dyn_cast<LoadSDNode>(
Value.getOperand(0));
21825 ST->getAlign(),
ST->getMemOperand()->getFlags(),
21835 if (
auto *CIdx = dyn_cast<ConstantSDNode>(
Idx)) {
21836 unsigned COffset = CIdx->getSExtValue() * EltVT.
getSizeInBits() / 8;
21838 PointerInfo =
ST->getPointerInfo().getWithOffset(COffset);
21843 return DAG.
getStore(Chain,
DL, Elt, NewPtr, PointerInfo,
ST->getAlign(),
21844 ST->getMemOperand()->getFlags());
21851 EVT MemVT =
ST->getMemoryVT();
21874 ST->isUnindexed()) {
21875 EVT SVT =
Value.getOperand(0).getValueType();
21882 if (((!LegalOperations &&
ST->isSimple()) ||
21885 DAG, *
ST->getMemOperand())) {
21887 ST->getMemOperand());
21892 if (
Value.isUndef() &&
ST->isUnindexed() && !
ST->isVolatile())
21899 if (*Alignment >
ST->getAlign() &&
21900 isAligned(*Alignment,
ST->getSrcValueOffset())) {
21903 ST->getMemoryVT(), *Alignment,
21904 ST->getMemOperand()->getFlags(),
ST->getAAInfo());
21914 if (
SDValue NewST = TransformFPLoadStorePair(
N))
21918 if (
SDValue Store = mergeTruncStores(ST))
21921 if (
ST->isUnindexed()) {
21924 if (findBetterNeighborChains(ST)) {
21929 Chain =
ST->getChain();
21933 if (
ST->isTruncatingStore() &&
ST->isUnindexed() &&
21934 Value.getValueType().isInteger() &&
21935 (!isa<ConstantSDNode>(
Value) ||
21936 !cast<ConstantSDNode>(
Value)->isOpaque())) {
21941 Value.getOperand(0).getValueType() ==
ST->getMemoryVT() &&
21944 ST->getMemOperand());
21946 APInt TruncDemandedBits =
21948 ST->getMemoryVT().getScalarSizeInBits());
21952 AddToWorklist(
Value.getNode());
21969 ST->getMemOperand());
21973 if (
auto *Cst = dyn_cast<ConstantSDNode>(
Value))
21974 if (!Cst->isOpaque()) {
21975 const APInt &CValue = Cst->getAPIntValue();
21976 APInt NewVal = CValue & TruncDemandedBits;
21977 if (NewVal != CValue) {
21981 ST->getMemoryVT(),
ST->getMemOperand());
21993 if (
auto *Ld = dyn_cast<LoadSDNode>(TruncVal)) {
21995 ST->isUnindexed() &&
ST->isSimple() &&
22006 if (
SDValue NewST = replaceStoreOfInsertLoad(ST))
22010 if (
StoreSDNode *ST1 = dyn_cast<StoreSDNode>(Chain)) {
22011 if (
ST->isUnindexed() &&
ST->isSimple() &&
22012 ST1->isUnindexed() && ST1->isSimple()) {
22014 ST1->getValue() ==
Value &&
ST->getMemoryVT() == ST1->getMemoryVT() &&
22015 ST->getAddressSpace() == ST1->getAddressSpace()) {
22022 !ST1->getBasePtr().isUndef() &&
22023 ST->getAddressSpace() == ST1->getAddressSpace()) {
22028 if (
ST->getMemoryVT().isScalableVector() ||
22029 ST1->getMemoryVT().isScalableVector()) {
22030 if (ST1->getBasePtr() ==
Ptr &&
22032 ST->getMemoryVT().getStoreSize())) {
22033 CombineTo(ST1, ST1->getChain());
22043 if (STBase.contains(DAG,
ST->getMemoryVT().getFixedSizeInBits(),
22045 ST1->getMemoryVT().getFixedSizeInBits())) {
22046 CombineTo(ST1, ST1->getChain());
22060 ST->getMemoryVT(), LegalOperations)) {
22062 Ptr,
ST->getMemoryVT(),
ST->getMemOperand());
22073 bool Changed = mergeConsecutiveStores(ST);
22074 if (!Changed)
break;
22083 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
22091 if (isa<ConstantFPSDNode>(
ST->getValue())) {
22092 if (
SDValue NewSt = replaceStoreOfFPConstant(ST))
22099 return ReduceLoadOpStoreWidth(
N);
22103 const auto *LifetimeEnd = cast<LifetimeSDNode>(
N);
22104 if (!LifetimeEnd->hasOffset())
22108 LifetimeEnd->getOffset(),
false);
22112 while (!Chains.
empty()) {
22131 if (!
ST->isSimple() ||
ST->isIndexed())
22133 const TypeSize StoreSize =
ST->getMemoryVT().getStoreSize();
22141 if (LifetimeEndBase.contains(DAG, LifetimeEnd->getSize() * 8, StoreBase,
22144 dbgs() <<
"\nwithin LIFETIME_END of : ";
22145 LifetimeEndBase.dump();
dbgs() <<
"\n");
22146 CombineTo(ST,
ST->getChain());
22189 if (!
ST->isSimple())
22222 !
Lo.getOperand(0).getValueType().isScalarInteger() ||
22223 Lo.getOperand(0).getValueSizeInBits() > HalfValBitSize ||
22225 !
Hi.getOperand(0).getValueType().isScalarInteger() ||
22226 Hi.getOperand(0).getValueSizeInBits() > HalfValBitSize)
22232 ?
Lo.getOperand(0).getValueType()
22233 :
Lo.getValueType();
22235 ?
Hi.getOperand(0).getValueType()
22236 :
Hi.getValueType();
22253 ST->getOriginalAlign(), MMOFlags, AAInfo);
22258 St0,
DL,
Hi,
Ptr,
ST->getPointerInfo().getWithOffset(HalfValBitSize / 8),
22259 ST->getOriginalAlign(), MMOFlags, AAInfo);
22270 unsigned InsIndex) {
22279 int ElementOffset = -1;
22288 while (!ArgWorkList.
empty()) {
22291 std::tie(ArgOffset, ArgVal) = ArgWorkList.
pop_back_val();
22293 if (ArgVal == InsertVal0) {
22294 ElementOffset = ArgOffset;
22300 int CurrentArgOffset =
22304 CurrentArgOffset -= Step;
22310 assert(CurrentArgOffset == ArgOffset);
22316 if (ElementOffset == -1) {
22317 if (!
Y.isUndef() || InsertVal0.
getValueType() !=
Y.getValueType())
22319 ElementOffset = Mask.size();
22323 NewMask.
assign(Mask.begin(), Mask.end());
22325 assert(NewMask[InsIndex] < (
int)(2 * Mask.size()) && NewMask[InsIndex] >= 0 &&
22326 "NewMask[InsIndex] is out of bound");
22335SDValue DAGCombiner::mergeInsertEltWithShuffle(
SDNode *
N,
unsigned InsIndex) {
22337 "Expected extract_vector_elt");
22338 SDValue InsertVal =
N->getOperand(1);
22341 auto *SVN = dyn_cast<ShuffleVectorSDNode>(Vec);
22354 return LegalShuffle;
22365SDValue DAGCombiner::combineInsertEltToShuffle(
SDNode *
N,
unsigned InsIndex) {
22367 "Expected extract_vector_elt");
22368 SDValue InsertVal =
N->getOperand(1);
22375 SDValue DestVec =
N->getOperand(0);
22381 if (NumSrcElts == 1)
22384 unsigned NumMaskVals = ExtendRatio * NumSrcElts;
22392 for (
unsigned i = 0; i != NumMaskVals; ++i) {
22393 if (i / NumSrcElts == InsIndex)
22394 Mask[i] = (i % NumSrcElts) + NumMaskVals;
22409 ConcatOps[0] = SubVec;
22415 AddToWorklist(PaddedSubV.
getNode());
22416 AddToWorklist(DestVecBC.
getNode());
22417 AddToWorklist(Shuf.
getNode());
22424SDValue DAGCombiner::combineInsertEltToLoad(
SDNode *
N,
unsigned InsIndex) {
22425 EVT VT =
N->getValueType(0);
22434 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(0));
22437 return InsIndex == P.index() || P.value() < 0 ||
22438 (InsIndex == 0 && P.value() == (int)P.index() - 1) ||
22439 (InsIndex == VT.getVectorNumElements() - 1 &&
22440 P.value() == (int)P.index() + 1);
22446 unsigned Extend = 0;
22450 Extend =
Scalar.getOpcode();
22454 auto *ScalarLoad = dyn_cast<LoadSDNode>(Scalar);
22464 auto *
VecLoad = dyn_cast<LoadSDNode>(Vec);
22468 int EltSize = ScalarLoad->getValueType(0).getScalarSizeInBits();
22469 if (EltSize == 0 || EltSize % 8 != 0 || !ScalarLoad->isSimple() ||
22472 ScalarLoad->getAddressSpace() !=
VecLoad->getAddressSpace())
22477 if (InsIndex == 0) {
22488 unsigned IsFast = 0;
22492 NewAlign,
VecLoad->getMemOperand()->getFlags(),
22504 InsIndex == 0 ? ScalarLoad->getPointerInfo()
22505 :
VecLoad->getPointerInfo().getWithOffset(EltSize / 8);
22508 ScalarLoad->getChain(),
Ptr, PtrInfo, NewAlign);
22521 auto *IndexC = dyn_cast<ConstantSDNode>(EltNo);
22548 unsigned Elt = IndexC->getZExtValue();
22551 if (NumElts == 1) {
22567 && isa<ConstantSDNode>(InVec.
getOperand(2))) {
22569 if (Elt < OtherElt) {
22573 AddToWorklist(NewOp.
getNode());
22579 if (
SDValue Shuf = mergeInsertEltWithShuffle(
N, Elt))
22582 if (
SDValue Shuf = combineInsertEltToShuffle(
N, Elt))
22585 if (
SDValue Shuf = combineInsertEltToLoad(
N, Elt))
22601 EVT EltVT = Elt.getValueType();
22602 MaxEltVT = MaxEltVT.
bitsGE(EltVT) ? MaxEltVT : EltVT;
22610 assert(Ops.
size() == NumElts &&
"Unexpected vector size");
22624 for (
SDValue CurVec = InVec; CurVec;) {
22626 if (CurVec.isUndef())
22627 return CanonicalizeBuildVector(Ops);
22631 for (
unsigned I = 0;
I != NumElts; ++
I)
22632 AddBuildVectorOp(Ops, CurVec.getOperand(
I),
I);
22633 return CanonicalizeBuildVector(Ops);
22638 AddBuildVectorOp(Ops, CurVec.getOperand(0), 0);
22639 return CanonicalizeBuildVector(Ops);
22644 if (
auto *CurIdx = dyn_cast<ConstantSDNode>(CurVec.getOperand(2)))
22645 if (CurIdx->getAPIntValue().ult(NumElts)) {
22646 unsigned Idx = CurIdx->getZExtValue();
22647 AddBuildVectorOp(Ops, CurVec.getOperand(1),
Idx);
22651 return CanonicalizeBuildVector(Ops);
22653 CurVec = CurVec->getOperand(0);
22661 auto *SVN = cast<ShuffleVectorSDNode>(CurVec);
22665 bool Merged =
true;
22674 Mask = std::move(NewMask);
22691 for (
unsigned I = 0;
I != NumElts; ++
I)
22704 for (
unsigned I = 0;
I != NumElts; ++
I)
22711 for (
unsigned I = 0;
I != NumElts; ++
I)
22715 return CanonicalizeBuildVector(Ops);
22722SDValue DAGCombiner::scalarizeExtractedVectorLoad(
SDNode *EVE,
EVT InVecVT,
22745 if (
auto *ConstEltNo = dyn_cast<ConstantSDNode>(EltNo)) {
22746 int Elt = ConstEltNo->getZExtValue();
22757 unsigned IsFast = 0;
22771 if (ResultVT.
bitsGT(VecEltVT)) {
22778 NewPtr, MPI, VecEltVT, Alignment,
22788 if (ResultVT.
bitsLT(VecEltVT))
22800 const SDLoc &
DL,
bool LegalTypes) {
22804 auto *IndexC = dyn_cast<ConstantSDNode>(Index);
22838 DL, ResVT, Op0, Op1, cast<CondCodeSDNode>(Vec->
getOperand(2))->get());
22842 if (ResVT != MVT::i1 &&
22855 return DAG.
getNode(Opc,
DL, ResVT, Op0, Op1);
22867bool DAGCombiner::refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
22884 auto *IndexC = dyn_cast<ConstantSDNode>(
N->getOperand(1));
22889 "Original ISD::EXTRACT_VECTOR_ELT is undefinend?");
22893 EVT ScalarVT =
N->getValueType(0);
22909 Entry(Entry &&) =
default;
22910 Entry(
SDNode *Producer_,
unsigned BitPos_,
int NumBits_)
22911 :
Producer(Producer_), BitPos(BitPos_), NumBits(NumBits_) {}
22914 Entry(
const Entry &) =
delete;
22915 Entry &operator=(
const Entry &) =
delete;
22916 Entry &operator=(Entry &&) =
delete;
22922 Worklist.
emplace_back(
N, VecEltBitWidth * IndexC->getZExtValue(),
22925 while (!Worklist.
empty()) {
22932 bool ProducerIsLeaf =
false;
22935 switch (
User->getOpcode()) {
22943 User->getValueSizeInBits(0));
22949 if (
auto *ShAmtC = dyn_cast<ConstantSDNode>(
User->
getOperand(1));
22953 unsigned ShAmt = ShAmtC->getZExtValue();
22961 ProducerIsLeaf =
true;
22969 if (ProducerIsLeaf)
22973 unsigned NewVecEltBitWidth = Leafs.
front().NumBits;
22976 if (NewVecEltBitWidth == VecEltBitWidth)
22986 if (!
all_of(Leafs, [NewVecEltBitWidth](
const Entry &E) {
22987 return (
unsigned)E.NumBits == NewVecEltBitWidth &&
22988 E.Producer->getValueSizeInBits(0) == NewVecEltBitWidth &&
22989 E.BitPos % NewVecEltBitWidth == 0;
23001 if (LegalOperations &&
23007 for (
const Entry &E : Leafs) {
23009 unsigned NewIndex = E.BitPos / NewVecEltBitWidth;
23011 "Creating out-of-bounds ISD::EXTRACT_VECTOR_ELT?");
23014 CombineTo(E.Producer, V);
23023 EVT ScalarVT =
N->getValueType(0);
23036 AddUsersToWorklist(VecOp.
getNode());
23060 auto *IndexC = dyn_cast<ConstantSDNode>(Index);
23071 "BUILD_VECTOR used for scalable vectors");
23072 unsigned IndexVal =
23080 if (ScalarVT == InEltVT)
23120 unsigned ExtractIndex = IndexC->getZExtValue();
23122 unsigned BCTruncElt = IsLE ? 0 : NumElts - 1;
23135 EVT XVT =
X.getValueType();
23137 "Extract element and scalar to vector can't change element type "
23138 "from FP to integer.");
23139 unsigned XBitWidth =
X.getValueSizeInBits();
23140 unsigned Scale = XBitWidth / VecEltBitWidth;
23141 BCTruncElt = IsLE ? 0 : Scale - 1;
23146 if (ExtractIndex < Scale && XBitWidth > VecEltBitWidth) {
23147 assert(XBitWidth % VecEltBitWidth == 0 &&
23148 "Scalar bitwidth must be a multiple of vector element bitwidth");
23150 if (ExtractIndex != BCTruncElt) {
23151 unsigned ShiftIndex =
23152 IsLE ? ExtractIndex : (Scale - 1) - ExtractIndex;
23170 auto *Shuf = cast<ShuffleVectorSDNode>(VecOp);
23172 int OrigElt = Shuf->getMaskElt(IndexC->getZExtValue());
23180 if (OrigElt < (
int)NumElts) {
23184 OrigElt -= NumElts;
23200 if (!LegalOperations ||
23212 return Use->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
23213 Use->getOperand(0) == VecOp &&
23214 isa<ConstantSDNode>(Use->getOperand(1));
23219 if (CstElt->getAPIntValue().ult(NumElts))
23220 DemandedElts.
setBit(CstElt->getZExtValue());
23239 if (refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
N))
23245 bool BCNumEltsChanged =
false;
23260 BCNumEltsChanged =
true;
23266 if (!LegalOperations && !IndexC && VecOp.
hasOneUse() &&
23269 auto *
VecLoad = dyn_cast<LoadSDNode>(VecOp);
23270 if (VecLoad &&
VecLoad->isSimple())
23271 return scalarizeExtractedVectorLoad(
N, VecVT, Index, VecLoad);
23276 if (!LegalOperations || !IndexC)
23282 int Elt = IndexC->getZExtValue();
23285 LN0 = cast<LoadSDNode>(VecOp);
23293 LN0 = cast<LoadSDNode>(VecOp.
getOperand(0));
23295 if (
auto *Shuf = dyn_cast<ShuffleVectorSDNode>(VecOp)) {
23306 if (BCNumEltsChanged)
23310 int Idx = (Elt > (int)NumElts) ? -1 : Shuf->getMaskElt(Elt);
23321 LN0 = cast<LoadSDNode>(VecOp);
23322 Elt = (
Idx < (int)NumElts) ?
Idx :
Idx - (int)NumElts;
23341 Index.getValueType());
23359 return scalarizeExtractedVectorLoad(
N, VecVT, Index, LN0);
23373 unsigned NumInScalars =
N->getNumOperands();
23375 EVT VT =
N->getValueType(0);
23382 EVT SourceType = MVT::Other;
23383 bool AllAnyExt =
true;
23385 for (
unsigned i = 0; i != NumInScalars; ++i) {
23388 if (
In.isUndef())
continue;
23394 if (!ZeroExt && !AnyExt) {
23395 SourceType = MVT::Other;
23400 EVT InTy =
In.getOperand(0).getValueType();
23403 if (SourceType == MVT::Other)
23406 else if (InTy != SourceType) {
23408 SourceType = MVT::Other;
23413 AllAnyExt &= AnyExt;
23421 SourceType != MVT::Other &&
23422 llvm::has_single_bit<uint32_t>(OutScalarTy.
getSizeInBits()) &&
23423 llvm::has_single_bit<uint32_t>(SourceType.
getSizeInBits());
23437 assert(ElemRatio > 1 &&
"Invalid element size ratio");
23445 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
23449 Cast.
isUndef()) &&
"Invalid cast opcode");
23455 unsigned Index = isLE ? (i * ElemRatio) :
23456 (i * ElemRatio + (ElemRatio - 1));
23458 assert(Index < Ops.size() &&
"Invalid index");
23465 "Invalid vector size");
23488 EVT VT =
N->getValueType(0);
23507 unsigned NumInScalars =
N->getNumOperands();
23510 auto PeekThroughBitcast = [](
SDValue Op) {
23512 return Op.getOperand(0);
23518 for (
unsigned i = 0; i != NumInScalars; ++i) {
23519 SDValue In = PeekThroughBitcast(
N->getOperand(i));
23521 if (
In.isUndef())
continue;
23526 In = PeekThroughBitcast(
In.getOperand(0));
23537 SDValue part = PeekThroughBitcast(
In.getOperand(0));
23541 }
else if (Src != part) {
23546 SDValue ShiftAmtVal =
In.getOperand(1);
23547 if (!isa<ConstantSDNode>(ShiftAmtVal))
23550 uint64_t ShiftAmt =
In.getConstantOperandVal(1);
23553 if (ShiftAmt != i * ScalarTypeBitsize)
23559 if (!Src || Src.getValueType().getSizeInBits() != VT.
getSizeInBits())
23568 unsigned LeftIdx,
bool DidSplitVec) {
23571 EVT VT =
N->getValueType(0);
23576 unsigned ShuffleNumElems = NumElems;
23586 assert(InVT2Size <= InVT1Size &&
23587 "Inputs must be sorted to be in non-increasing vector size order.");
23591 if (InVT1 != VT || InVT2 != VT) {
23592 if ((VTSize % InVT1Size == 0) && InVT1 == InVT2) {
23595 unsigned NumConcats = VTSize / InVT1Size;
23596 assert(NumConcats >= 2 &&
"Concat needs at least two inputs!");
23598 ConcatOps[0] = VecIn1;
23599 ConcatOps[1] = VecIn2 ? VecIn2 : DAG.
getUNDEF(InVT1);
23602 }
else if (InVT1Size == VTSize * 2) {
23614 Vec2Offset = NumElems;
23616 assert(InVT2Size <= InVT1Size &&
23617 "Second input is not going to be larger than the first one.");
23623 if (LegalOperations &&
23630 if (InVT1 != InVT2) {
23634 DAG.
getUNDEF(InVT1), VecIn2, ZeroIdx);
23636 ShuffleNumElems = NumElems * 2;
23638 }
else if (InVT2Size * 2 == VTSize && InVT1Size == VTSize) {
23640 ConcatOps[0] = VecIn2;
23642 }
else if (InVT1Size / VTSize > 1 && InVT1Size % VTSize == 0) {
23650 assert(InVT2Size <= InVT1Size &&
23651 "Second input is not going to be larger than the first one.");
23660 if (InVT1 != InVT2) {
23662 DAG.
getUNDEF(InVT1), VecIn2, ZeroIdx);
23664 ShuffleNumElems = InVT1Size / VTSize * NumElems;
23680 for (
unsigned i = 0; i != NumElems; ++i) {
23681 if (VectorMask[i] <= 0)
23684 unsigned ExtIndex =
N->getOperand(i).getConstantOperandVal(1);
23685 if (VectorMask[i] == (
int)LeftIdx) {
23686 Mask[i] = ExtIndex;
23687 }
else if (VectorMask[i] == (
int)LeftIdx + 1) {
23688 Mask[i] = Vec2Offset + ExtIndex;
23701 if (ShuffleNumElems > NumElems)
23714 for (
int i = 0; i != NumBVOps; ++i) {
23746 if (DestSize % SrcSize != 0 ||
23752 int ZextRatio = DestSize / SrcSize;
23753 int NumMaskElts = NumBVOps * ZextRatio;
23755 for (
int i = 0; i != NumMaskElts; ++i) {
23756 if (i / ZextRatio == ZextElt) {
23777 ZeroVec, ShufMask, DAG);
23784template <
typename R,
typename T>
23788 return static_cast<decltype(std::distance(
Range.begin(),
I))
>(-1);
23789 return std::distance(
Range.begin(),
I);
23797 EVT VT =
N->getValueType(0);
23810 bool UsesZeroVector =
false;
23811 unsigned NumElems =
N->getNumOperands();
23825 unsigned OneConstExtractIndex = ~0
u;
23828 unsigned NumExtracts = 0;
23830 for (
unsigned i = 0; i != NumElems; ++i) {
23840 UsesZeroVector =
true;
23850 SDValue ExtractedFromVec =
Op.getOperand(0);
23853 auto *ExtractIdx = dyn_cast<ConstantSDNode>(
Op.getOperand(1));
23857 if (ExtractIdx->getAsAPIntVal().uge(
23866 OneConstExtractIndex = ExtractIdx->getZExtValue();
23878 VectorMask[i] =
Idx;
23882 if (VecIn.
size() < 2)
23889 bool DidSplitVec =
false;
23890 if (VecIn.
size() == 2) {
23899 if (NumExtracts == 1 &&
23905 unsigned MaxIndex = 0;
23906 unsigned NearestPow2 = 0;
23911 for (
unsigned i = 0; i < NumElems; i++) {
23912 if (VectorMask[i] <= 0)
23914 unsigned Index =
N->getOperand(i).getConstantOperandVal(1);
23915 IndexVec[i] =
Index;
23916 MaxIndex = std::max(MaxIndex, Index);
23920 if (InVT.
isSimple() && NearestPow2 > 2 && MaxIndex < NearestPow2 &&
23921 NumElems * 2 < NearestPow2) {
23922 unsigned SplitSize = NearestPow2 / 2;
23935 DidSplitVec =
true;
23937 for (
unsigned i = 0; i < NumElems; i++) {
23938 if (VectorMask[i] <= 0)
23940 VectorMask[i] = (IndexVec[i] < SplitSize) ? 1 : 2;
23953 b.getValueType().getVectorNumElements();
23958 for (
int &SourceVectorIndex : VectorMask) {
23959 if (SourceVectorIndex <= 0)
23963 VecIn[SourceVectorIndex] == SortedVecIn[
Idx] &&
"Remapping failure");
23964 SourceVectorIndex =
Idx;
23967 VecIn = std::move(SortedVecIn);
23985 for (
unsigned In = 0, Len = (VecIn.
size() / 2); In < Len; ++In) {
23986 unsigned LeftIdx = 2 *
In + 1;
23987 SDValue VecLeft = VecIn[LeftIdx];
23989 (LeftIdx + 1) < VecIn.
size() ? VecIn[LeftIdx + 1] :
SDValue();
23991 if (
SDValue Shuffle = createBuildVecShuffle(
DL,
N, VectorMask, VecLeft,
23992 VecRight, LeftIdx, DidSplitVec))
24000 if (UsesZeroVector)
24005 if (Shuffles.
size() == 1)
24006 return Shuffles[0];
24009 for (
int &Vec : VectorMask)
24011 Vec = Shuffles.
size() - 1;
24013 Vec = (Vec - 1) / 2;
24027 if (Shuffles.
size() % 2)
24030 for (
unsigned CurSize = Shuffles.
size(); CurSize > 1; CurSize /= 2) {
24032 Shuffles[CurSize] = DAG.
getUNDEF(VT);
24035 for (
unsigned In = 0, Len = CurSize / 2;
In <
Len; ++
In) {
24042 L.use_empty() &&
L.getOperand(1).isUndef() &&
24043 L.getOperand(0).getValueType() ==
L.getValueType();
24044 if (IsLeftShuffle) {
24045 LMask = cast<ShuffleVectorSDNode>(
L.getNode())->getMask();
24046 L =
L.getOperand(0);
24051 R.use_empty() &&
R.getOperand(1).isUndef() &&
24052 R.getOperand(0).getValueType() ==
R.getValueType();
24053 if (IsRightShuffle) {
24054 RMask = cast<ShuffleVectorSDNode>(
R.getNode())->getMask();
24055 R =
R.getOperand(0);
24057 for (
unsigned I = 0;
I != NumElems; ++
I) {
24058 if (VectorMask[
I] ==
Left) {
24062 VectorMask[
I] =
In;
24063 }
else if (VectorMask[
I] ==
Right) {
24065 if (IsRightShuffle)
24066 Mask[
I] = RMask[
I] + NumElems;
24067 VectorMask[
I] =
In;
24074 return Shuffles[0];
24082 if (LegalOperations)
24085 EVT VT =
N->getValueType(0);
24087 bool FoundZeroExtend =
false;
24089 auto checkElem = [&](
SDValue Op) -> int64_t {
24090 unsigned Opc =
Op.getOpcode();
24095 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op.getOperand(0).getOperand(1)))
24096 return C->getZExtValue();
24104 int64_t
Offset = checkElem(Op0);
24108 unsigned NumElems =
N->getNumOperands();
24110 EVT InSVT =
In.getValueType().getScalarType();
24118 for (
unsigned i = 1; i != NumElems; ++i) {
24119 if ((
Offset + i) != checkElem(
N->getOperand(i)))
24137SDValue DAGCombiner::convertBuildVecZextToBuildVecWithZeros(
SDNode *
N) {
24146 EVT VT =
N->getValueType(0);
24147 EVT OpVT =
N->getOperand(0).getValueType();
24161 unsigned ActiveBits = 0;
24166 if (
auto *Cst = dyn_cast<ConstantSDNode>(
Op)) {
24167 unsigned OpActiveBits =
24168 Cst->getAPIntValue().trunc(EltBitwidth).getActiveBits();
24169 if (OpActiveBits == 0) {
24170 KnownZeroOps.setBit(
I.index());
24178 if (
I.index() != 0)
24184 unsigned CurrActiveBits =
24185 Op.getOperand(0).getValueSizeInBits().getFixedValue();
24186 assert(!ActiveBits &&
"Already encountered non-constant-zero operand?");
24187 ActiveBits = CurrActiveBits;
24189 if (2 * ActiveBits > EltBitwidth)
24194 if (ActiveBits == 0)
24199 EVT NewScalarIntVT, NewIntVT;
24200 std::optional<unsigned> Factor;
24205 assert(2 * ActiveBits <= EltBitwidth &&
24206 "We know that half or less bits of the element are active.");
24207 for (
unsigned Scale = EltBitwidth / ActiveBits; Scale >= 2; --Scale) {
24208 if (EltBitwidth % Scale != 0)
24210 unsigned ChunkBitwidth = EltBitwidth / Scale;
24211 assert(ChunkBitwidth >= ActiveBits &&
"As per starting point.");
24214 Scale *
N->getNumOperands());
24216 (LegalOperations &&
24234 assert(!
Op.isUndef() &&
"FIXME: after allowing UNDEF's, handle them here.");
24235 unsigned SrcOpIdx =
I.index();
24236 if (KnownZeroOps[SrcOpIdx]) {
24237 NewOps.
append(*Factor, ZeroOp);
24243 NewOps.
append(*Factor - 1, ZeroOp);
24252 EVT VT =
N->getValueType(0);
24266 if (!LegalOperations) {
24267 SDValue Splat = cast<BuildVectorSDNode>(
N)->getSplatValue();
24288 if (!LegalTypes && (
N->getNumOperands() > 1)) {
24293 if (
auto CNode = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
24298 int Offset = checkElem(Op0);
24299 for (
unsigned i = 0; i <
N->getNumOperands(); ++i) {
24300 if (
Offset + i != checkElem(
N->getOperand(i))) {
24310 ((
Offset %
N->getValueType(0).getVectorNumElements()) ==
24316 if (
SDValue V = convertBuildVecZextToZext(
N))
24319 if (
SDValue V = convertBuildVecZextToBuildVecWithZeros(
N))
24322 if (
SDValue V = reduceBuildVecExtToExtBuildVec(
N))
24325 if (
SDValue V = reduceBuildVecTruncToBitCast(
N))
24328 if (
SDValue V = reduceBuildVecToShuffle(
N))
24335 assert(!
V.isUndef() &&
"Splat of undef should have been handled earlier");
24344 EVT OpVT =
N->getOperand(0).getValueType();
24351 EVT VT =
N->getValueType(0);
24360 !
Op.getOperand(0).getValueType().isVector())
24369 EVT LastOpVT = Ops.
back().getValueType();
24371 AnyFPVT = LastOpVT;
24379 if (AnyFPVT !=
EVT()) {
24382 if (
Op.getValueType() == SVT)
24401 EVT VT =
N->getValueType(0);
24411 if (!FirstConcat) {
24412 SubVT =
Op.getOperand(0).getValueType();
24418 if (SubVT !=
Op.getOperand(0).getValueType())
24421 assert(FirstConcat &&
"Concat of all-undefs found");
24425 if (
Op.isUndef()) {
24429 ConcatOps.
append(
Op->op_begin(),
Op->op_end());
24439 EVT VT =
N->getValueType(0);
24440 EVT OpVT =
N->getOperand(0).getValueType();
24456 if (
Op.isUndef()) {
24457 Mask.append((
unsigned)NumOpElts, -1);
24466 int ExtIdx =
Op.getConstantOperandVal(1);
24475 Mask.append((
unsigned)NumOpElts, -1);
24486 if (0 == (NumExtElts % NumElts))
24487 ExtIdx /= (NumExtElts / NumElts);
24488 else if (0 == (NumElts % NumExtElts))
24489 ExtIdx *= (NumElts / NumExtElts);
24494 if (SV0.
isUndef() || SV0 == ExtVec) {
24496 for (
int i = 0; i != NumOpElts; ++i)
24497 Mask.push_back(i + ExtIdx);
24498 }
else if (SV1.
isUndef() || SV1 == ExtVec) {
24500 for (
int i = 0; i != NumOpElts; ++i)
24501 Mask.push_back(i + ExtIdx + NumElts);
24513 unsigned CastOpcode =
N->getOperand(0).getOpcode();
24514 switch (CastOpcode) {
24530 EVT SrcVT =
N->getOperand(0).getOperand(0).getValueType();
24538 if (
Op.getOpcode() != CastOpcode || !
Op.hasOneUse() ||
24539 Op.getOperand(0).getValueType() != SrcVT)
24547 EVT VT =
N->getValueType(0);
24552 switch (CastOpcode) {
24572 return DAG.
getNode(CastOpcode,
DL, VT, NewConcat);
24580 bool LegalOperations) {
24581 EVT VT =
N->getValueType(0);
24582 EVT OpVT =
N->getOperand(0).getValueType();
24587 if (
N->getNumOperands() != 2)
24592 (LegalOperations &&
24603 if (
auto *CurSVN = dyn_cast<ShuffleVectorSDNode>(
Op);
24604 CurSVN && CurSVN->getOperand(1).
isUndef() &&
N->isOnlyUserOf(CurSVN) &&
24607 return !Op.isUndef() &&
24608 (Op.getNode() == CurSVN || is_contained(CurSVN->ops(), Op));
24631 std::iota(FirstShufOpIdentityMask.
begin(), FirstShufOpIdentityMask.
end(), 0);
24632 std::iota(SecondShufOpIdentityMask.
begin(), SecondShufOpIdentityMask.
end(),
24639 assert(!
Op.isUndef() &&
"Not expecting to concatenate UNDEF.");
24640 if (
Op.getNode() == SVN) {
24661 std::array<SDValue, 2> ShufOps;
24662 for (
auto I :
zip(SVN->
ops(), ShufOps)) {
24664 SDValue &NewShufOp = std::get<1>(
I);
24670 ShufOpParts[0] = ShufOp;
24680 if (
N->getNumOperands() == 1)
24681 return N->getOperand(0);
24684 EVT VT =
N->getValueType(0);
24690 [](
const SDValue &
Op) { return Op.isUndef(); })) {
24692 assert(
In.getValueType().isVector() &&
"Must concat vectors");
24702 !(LegalDAG &&
In.getValueType().isScalableVector())) {
24703 unsigned NumOps =
N->getNumOperands() *
In.getNumOperands();
24705 Ops.resize(NumOps, DAG.
getUNDEF(Ops[0].getValueType()));
24715 EVT SVT =
Scalar.getValueType().getVectorElementType();
24716 if (SVT ==
Scalar.getOperand(0).getValueType())
24721 if (!
Scalar.getValueType().isVector() &&
In.hasOneUse()) {
24740 if (VNTNumElms < 2)
24756 auto IsBuildVectorOrUndef = [](
const SDValue &
Op) {
24767 bool FoundMinVT =
false;
24770 EVT OpSVT =
Op.getOperand(0).getValueType();
24771 MinVT = (!FoundMinVT || OpSVT.
bitsLE(MinVT)) ? OpSVT : MinVT;
24774 assert(FoundMinVT &&
"Concat vector type mismatch");
24778 EVT OpVT =
Op.getValueType();
24787 Opnds.
append(
Op->op_begin(),
Op->op_begin() + NumElts);
24789 for (
unsigned i = 0; i != NumElts; ++i)
24797 "Concat vector type mismatch");
24820 N, DAG, TLI, LegalTypes, LegalOperations))
24830 unsigned PartNumElem =
24831 N->getOperand(0).getValueType().getVectorMinNumElements();
24833 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
24844 if (SingleSource.
getNode()) {
24845 if (
Op.getOperand(0) != SingleSource)
24848 SingleSource =
Op.getOperand(0);
24858 unsigned IdentityIndex = i * PartNumElem;
24859 if (
Op.getConstantOperandAPInt(1) != IdentityIndex)
24864 return SingleSource;
24873 V.getOperand(1).getValueType() == SubVT && V.getOperand(2) == Index) {
24874 return V.getOperand(1);
24876 auto *IndexC = dyn_cast<ConstantSDNode>(Index);
24878 V.getOperand(0).getValueType() == SubVT &&
24881 return V.getOperand(SubIdx);
24888 bool LegalOperations) {
24891 unsigned BinOpcode = BinOp.
getOpcode();
24897 if (VecVT != Bop0.
getValueType() || VecVT != Bop1.getValueType())
24911 if (!Sub0 || !Sub1)
24917 return DAG.
getNode(BinOpcode,
SDLoc(Extract), SubVT, Sub0, Sub1,
24924 bool LegalOperations) {
24932 auto *ExtractIndexC = dyn_cast<ConstantSDNode>(Extract->
getOperand(1));
24933 if (!ExtractIndexC)
24949 if (
C &&
C->getValueAPF().isNegZero())
24962 unsigned ExtractIndex = ExtractIndexC->getZExtValue();
24964 "Extract index is not a multiple of the vector length.");
24969 if (WideWidth % NarrowWidth != 0)
24974 unsigned NarrowingRatio = WideWidth / NarrowWidth;
24976 if (WideNumElts % NarrowingRatio != 0)
24981 WideNumElts / NarrowingRatio);
25008 if (NarrowingRatio != 2)
25023 return V.getOperand(ConcatOpNum);
25029 if (SubVecL || SubVecR) {
25060 auto *Ld = dyn_cast<LoadSDNode>(Extract->
getOperand(0));
25080 assert(Index % NumElts == 0 &&
"The extract subvector index is not a "
25081 "multiple of the result's element count");
25100 if (
Offset.isScalable()) {
25123 bool LegalOperations) {
25125 "Must only be called on EXTRACT_SUBVECTOR's");
25130 EVT NarrowVT =
N->getValueType(0);
25136 auto *WideShuffleVector = dyn_cast<ShuffleVectorSDNode>(N0);
25137 if (!WideShuffleVector)
25141 if (!WideShuffleVector->hasOneUse())
25145 if (LegalOperations &&
25149 uint64_t FirstExtractedEltIdx =
N->getConstantOperandVal(1);
25151 assert((FirstExtractedEltIdx % NumEltsExtracted) == 0 &&
25152 "Extract index is not a multiple of the output vector length.");
25157 NewMask.
reserve(NumEltsExtracted);
25159 DemandedSubvectors;
25162 for (
int M : WideShuffleVector->getMask().slice(FirstExtractedEltIdx,
25163 NumEltsExtracted)) {
25164 assert((M >= -1) && (M < (2 * WideNumElts)) &&
25165 "Out-of-bounds shuffle mask?");
25174 int WideShufOpIdx = M / WideNumElts;
25176 int OpEltIdx = M % WideNumElts;
25178 assert((OpEltIdx + WideShufOpIdx * WideNumElts) == M &&
25179 "Shuffle mask vector decomposition failure.");
25182 int OpSubvecIdx = OpEltIdx / NumEltsExtracted;
25184 int OpEltIdxInSubvec = OpEltIdx % NumEltsExtracted;
25186 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted) == OpEltIdx &&
25187 "Shuffle mask subvector decomposition failure.");
25189 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted +
25190 WideShufOpIdx * WideNumElts) == M &&
25191 "Shuffle mask full decomposition failure.");
25193 SDValue Op = WideShuffleVector->getOperand(WideShufOpIdx);
25195 if (
Op.isUndef()) {
25201 const std::pair<SDValue, int> DemandedSubvector =
25202 std::make_pair(
Op, OpSubvecIdx);
25204 if (DemandedSubvectors.insert(DemandedSubvector)) {
25205 if (DemandedSubvectors.size() > 2)
25208 int Index = NumEltsExtracted * OpSubvecIdx;
25216 getFirstIndexOf(DemandedSubvectors.getArrayRef(), DemandedSubvector);
25217 assert((NewOpIdx == 0 || NewOpIdx == 1) &&
"Unexpected operand index.");
25219 int AdjM = OpEltIdxInSubvec + NewOpIdx * NumEltsExtracted;
25222 assert(NewMask.
size() == (
unsigned)NumEltsExtracted &&
"Produced bad mask.");
25223 assert(DemandedSubvectors.size() <= 2 &&
25224 "Should have ended up demanding at most two subvectors.");
25227 if (DemandedSubvectors.empty())
25233 any_of(NewMask, [](
int M) {
return M < 0; }))
25234 for (
auto &DemandedSubvector : DemandedSubvectors)
25235 if (DemandedSubvector.second != 0)
25249 for (
const std::pair<SDValue /*Op*/, int /*SubvectorIndex*/>
25250 &DemandedSubvector : DemandedSubvectors) {
25252 int Index = NumEltsExtracted * DemandedSubvector.second;
25255 DemandedSubvector.first, IndexC));
25258 "Should end up with either one or two ops");
25261 if (NewOps.
size() == 1)
25268 EVT NVT =
N->getValueType(0);
25270 uint64_t ExtIdx =
N->getConstantOperandVal(1);
25285 V.getConstantOperandVal(1)) &&
25305 unsigned InsIdx =
V.getConstantOperandVal(2);
25307 if (InsIdx <= ExtIdx && (ExtIdx + NumSubElts) <= (InsIdx + NumInsElts) &&
25310 V.getValueType().isFixedLengthVector())
25318 V.getOperand(0).getValueType().isVector() &&
25323 unsigned DestNumElts =
V.getValueType().getVectorMinNumElements();
25324 if ((SrcNumElts % DestNumElts) == 0) {
25325 unsigned SrcDestRatio = SrcNumElts / DestNumElts;
25332 V.getOperand(0), NewIndex);
25336 if ((DestNumElts % SrcNumElts) == 0) {
25337 unsigned DestSrcRatio = DestNumElts / SrcNumElts;
25342 if ((ExtIdx % DestSrcRatio) == 0) {
25343 unsigned IndexValScaled = ExtIdx / DestSrcRatio;
25350 V.getOperand(0), NewIndex);
25358 V.getOperand(0), NewIndex);
25368 EVT ConcatSrcVT =
V.getOperand(0).getValueType();
25370 "Concat and extract subvector do not change element type");
25371 assert((ExtIdx % ExtNumElts) == 0 &&
25372 "Extract index is not a multiple of the input vector length.");
25375 unsigned ConcatOpIdx = ExtIdx / ConcatSrcNumElts;
25381 return V.getOperand(ConcatOpIdx);
25389 ConcatSrcNumElts % ExtNumElts == 0) {
25390 unsigned NewExtIdx = ExtIdx - ConcatOpIdx * ConcatSrcNumElts;
25391 assert(NewExtIdx + ExtNumElts <= ConcatSrcNumElts &&
25392 "Trying to extract from >1 concat operand?");
25393 assert(NewExtIdx % ExtNumElts == 0 &&
25394 "Extract index is not a multiple of the input vector length.");
25397 V.getOperand(ConcatOpIdx), NewIndexC);
25409 EVT InVT =
V.getValueType();
25413 if (ExtractSize % EltSize == 0) {
25414 unsigned NumElems = ExtractSize / EltSize;
25417 NumElems == 1 ? EltVT
25425 if (NumElems == 1) {
25426 SDValue Src =
V->getOperand(IdxVal);
25427 if (EltVT != Src.getValueType())
25443 EVT SmallVT =
V.getOperand(1).getValueType();
25444 if (!NVT.
bitsEq(SmallVT))
25452 uint64_t InsIdx =
V.getConstantOperandVal(2);
25462 DAG.
getBitcast(
N->getOperand(0).getValueType(),
V.getOperand(0)),
25492 unsigned HalfNumElts = NumElts / 2;
25495 for (
unsigned i = 0; i != NumElts; ++i) {
25499 if ((Mask[i] % NumElts) >= HalfNumElts)
25501 int M = Mask[i] < (int)NumElts ? Mask[i] : Mask[i] - (
int)HalfNumElts;
25502 if (i < HalfNumElts)
25505 Mask1[i - HalfNumElts] = M;
25528 EVT VT =
N->getValueType(0);
25539 unsigned NumConcats = NumElts / NumElemsPerConcat;
25541 auto IsUndefMaskElt = [](
int i) {
return i == -1; };
25546 if (NumElemsPerConcat * 2 == NumElts && N1.
isUndef() &&
25547 llvm::all_of(Mask.slice(NumElemsPerConcat, NumElemsPerConcat),
25551 Mask.slice(0, NumElemsPerConcat));
25558 for (
unsigned I = 0;
I != NumConcats; ++
I) {
25559 unsigned Begin =
I * NumElemsPerConcat;
25560 ArrayRef<int> SubMask = Mask.slice(Begin, NumElemsPerConcat);
25569 for (
int i = 0; i != (int)NumElemsPerConcat; ++i) {
25570 if (IsUndefMaskElt(SubMask[i]))
25572 if ((SubMask[i] % (
int)NumElemsPerConcat) != i)
25574 int EltOpIdx = SubMask[i] / NumElemsPerConcat;
25575 if (0 <= OpIdx && EltOpIdx != OpIdx)
25579 assert(0 <= OpIdx &&
"Unknown concat_vectors op");
25633 bool IsSplat =
false;
25634 auto *BV0 = dyn_cast<BuildVectorSDNode>(N0);
25635 auto *BV1 = dyn_cast<BuildVectorSDNode>(N1);
25637 if (
SDValue Splat0 = BV0->getSplatValue())
25638 IsSplat = (Splat0 == BV1->getSplatValue());
25642 for (
int M : SVN->
getMask()) {
25645 int Idx = M < (int)NumElts ? M : M - NumElts;
25646 SDValue &S = (M < (int)NumElts ? N0 : N1);
25648 Op = S.getOperand(
Idx);
25663 if (!IsSplat && !DuplicateOps.
insert(
Op).second)
25674 SVT = (SVT.
bitsLT(
Op.getValueType()) ?
Op.getValueType() : SVT);
25690 unsigned Opcode,
EVT VT, std::function<
bool(
unsigned)>
Match,
25692 bool LegalOperations) {
25697 return std::nullopt;
25705 for (
unsigned Scale = 2; Scale < NumElts; Scale *= 2) {
25707 if (NumElts % Scale != 0)
25721 return std::nullopt;
25730 bool LegalOperations) {
25740 Mask = SVN->
getMask()](
unsigned Scale) {
25741 for (
unsigned i = 0; i != NumElts; ++i) {
25744 if ((i % Scale) == 0 && Mask[i] == (int)(i / Scale))
25756 Opcode, VT, isAnyExtend, DAG, TLI,
true, LegalOperations);
25768 bool LegalOperations) {
25769 bool LegalTypes =
true;
25781 auto ForEachDecomposedIndice = [NumElts, &Mask](
auto Fn) {
25782 for (
int &Indice : Mask) {
25785 int OpIdx = (
unsigned)Indice < NumElts ? 0 : 1;
25786 int OpEltIdx = (
unsigned)Indice < NumElts ? Indice : Indice - NumElts;
25787 Fn(Indice, OpIdx, OpEltIdx);
25792 std::array<APInt, 2> OpsDemandedElts;
25793 for (
APInt &OpDemandedElts : OpsDemandedElts)
25795 ForEachDecomposedIndice(
25796 [&OpsDemandedElts](
int &Indice,
int OpIdx,
int OpEltIdx) {
25797 OpsDemandedElts[OpIdx].setBit(OpEltIdx);
25801 std::array<APInt, 2> OpsKnownZeroElts;
25802 for (
auto I :
zip(SVN->
ops(), OpsDemandedElts, OpsKnownZeroElts))
25810 bool HadZeroableElts =
false;
25811 ForEachDecomposedIndice([&OpsKnownZeroElts, &HadZeroableElts](
25812 int &Indice,
int OpIdx,
int OpEltIdx) {
25813 if (OpsKnownZeroElts[OpIdx][OpEltIdx]) {
25815 HadZeroableElts =
true;
25823 if (!HadZeroableElts)
25831 Mask.size() % ScaledMask.
size() == 0 &&
"Unexpected mask widening.");
25832 int Prescale = Mask.size() / ScaledMask.
size();
25834 NumElts = ScaledMask.
size();
25835 EltSizeInBits *= Prescale;
25847 auto isZeroExtend = [NumElts, &ScaledMask](
unsigned Scale) {
25848 assert(Scale >= 2 && Scale <= NumElts && NumElts % Scale == 0 &&
25849 "Unexpected mask scaling factor.");
25851 for (
unsigned SrcElt = 0, NumSrcElts = NumElts / Scale;
25852 SrcElt != NumSrcElts; ++SrcElt) {
25855 assert(MaskChunk.
size() == Scale &&
"Unexpected mask size.");
25856 Mask = Mask.drop_front(MaskChunk.
size());
25859 if (
int FirstIndice = MaskChunk[0]; (
unsigned)FirstIndice != SrcElt)
25864 [](
int Indice) { return Indice == -2; }))
25867 assert(Mask.empty() &&
"Did not process the whole mask?");
25872 for (
bool Commuted : {
false,
true}) {
25877 Opcode, PrescaledVT, isZeroExtend, DAG, TLI, LegalTypes,
25913 if (ExtDstSizeInBits % ExtSrcSizeInBits != 0)
25915 unsigned ExtScale = ExtDstSizeInBits / ExtSrcSizeInBits;
25920 auto isTruncate = [&Mask, &NumElts](
unsigned Scale) {
25921 for (
unsigned i = 0; i != NumElts; ++i) {
25924 if ((i * Scale) < NumElts && Mask[i] == (int)(i * Scale))
25934 if (EltSizeInBits != ExtSrcSizeInBits)
25939 if (isTruncate(ExtScale))
25962 APInt DemandedElts(NumElts, 0);
25966 assert((
unsigned)
Idx < NumElts &&
"Out-of-bounds shuffle indice?");
25969 assert(DemandedElts.
popcount() > 1 &&
"Is a splat shuffle already?");
25974 std::optional<unsigned> MinNonUndefIdx;
25976 if (
Idx < 0 || UndefElts[
Idx])
25978 MinNonUndefIdx = std::min<unsigned>(
Idx, MinNonUndefIdx.value_or(~0U));
25980 if (!MinNonUndefIdx)
25982 assert(*MinNonUndefIdx < NumElts &&
"Expected valid element index.");
25984 for (
int &
Idx : SplatMask) {
25989 Idx = UndefElts[
Idx] ? -1 : *MinNonUndefIdx;
25991 assert(SplatMask != Shuf->
getMask() &&
"Expected mask to change!");
26009 assert(ShufMask.
size() == SplatMask.
size() &&
"Mask length mismatch");
26027 auto CanSimplifyToExistingSplat = [](
ArrayRef<int> UserMask,
26029 for (
unsigned i = 0, e = UserMask.
size(); i != e; ++i)
26030 if (UserMask[i] != -1 && SplatMask[i] == -1 &&
26031 SplatMask[UserMask[i]] != -1)
26035 if (CanSimplifyToExistingSplat(ShufMask, SplatMask))
26041 for (
int Idx : ShufMask)
26054 bool LegalOperations) {
26071 if (VTLanes <= InLanes || VTLanes % InLanes != 0 ||
26072 (LegalOperations &&
26075 int Factor = VTLanes / InLanes;
26102 auto *InnerShuf = dyn_cast<ShuffleVectorSDNode>(OuterShuf->
getOperand(0));
26103 if (!InnerShuf || !InnerShuf->getOperand(1).isUndef())
26108 unsigned NumElts = OuterMask.
size();
26109 assert(NumElts == InnerMask.
size() &&
"Mask length mismatch");
26111 int SplatIndex = -1;
26112 for (
unsigned i = 0; i != NumElts; ++i) {
26114 int OuterMaskElt = OuterMask[i];
26115 if (OuterMaskElt == -1)
26119 int InnerMaskElt = InnerMask[OuterMaskElt];
26120 if (InnerMaskElt == -1)
26124 if (SplatIndex == -1)
26125 SplatIndex = InnerMaskElt;
26128 if (SplatIndex != InnerMaskElt)
26131 CombinedMask[i] = InnerMaskElt;
26133 assert((
all_of(CombinedMask, [](
int M) {
return M == -1; }) ||
26135 "Expected a splat mask");
26139 assert(VT == InnerShuf->getValueType(0) &&
"Expected matching shuffle types");
26144 InnerShuf->getOperand(1), CombinedMask);
26152 int MaskSize = Mask.size();
26153 int EltFromOp0 = -1;
26158 for (
int i = 0; i != MaskSize; ++i) {
26159 if (Mask[i] >= 0 && Mask[i] < MaskSize) {
26161 if (EltFromOp0 != -1)
26164 }
else if (Mask[i] != i + MaskSize) {
26184 if (ShufOp0Index == -1) {
26188 if (ShufOp0Index == -1)
26192 Mask = CommutedMask;
26200 assert(Mask[ShufOp0Index] >= 0 && Mask[ShufOp0Index] < (
int)Mask.size() &&
26201 "Shuffle mask value must be from operand 0");
26219 Op1, Elt, NewInsIndex);
26231 auto *Shuf0 = dyn_cast<ShuffleVectorSDNode>(Shuf->
getOperand(0));
26237 for (
int i = 0, e = (
int)Mask.size(); i != e; ++i) {
26241 assert(Mask[i] >= 0 && Mask[i] < e &&
"Unexpected shuffle mask value");
26245 if (Mask0[Mask[i]] != Mask0[i])
26254 EVT VT =
N->getValueType(0);
26279 bool Changed =
false;
26281 for (
unsigned i = 0; i != NumElts; ++i) {
26283 if (
Idx >= (
int)NumElts) {
26332 if (
auto *
Idx = dyn_cast<ConstantSDNode>(N0.
getOperand(2)))
26333 if (
Idx->getAPIntValue() == SplatIndex)
26359 SDValue ConvInput =
V->getOperand(0);
26366 assert(
V->getNumOperands() == NumElts &&
26367 "BUILD_VECTOR has wrong number of operands");
26369 bool AllSame =
true;
26370 for (
unsigned i = 0; i != NumElts; ++i) {
26371 if (!
V->getOperand(i).isUndef()) {
26372 Base =
V->getOperand(i);
26377 if (!
Base.getNode())
26379 for (
unsigned i = 0; i != NumElts; ++i) {
26380 if (
V->getOperand(i) !=
Base) {
26391 SDValue Splatted =
V->getOperand(SplatIndex);
26395 for (
unsigned i = 0; i != NumElts; ++i) {
26404 if (
V->getValueType(0) != VT)
26443 int HalfNumElts = (int)NumElts / 2;
26445 for (
unsigned i = 0; i != NumElts; ++i) {
26447 if (
Idx >= HalfNumElts) {
26448 assert(
Idx < (
int)NumElts &&
"Shuffle mask chooses undef op");
26449 Idx -= HalfNumElts;
26470 EVT SubVT =
RHS.getOperand(0).getValueType();
26471 int NumSubVecs =
RHS.getNumOperands();
26473 assert((NumElts % NumSubElts) == 0 &&
"Subvector mismatch");
26478 if (
all_of(Mask, [NumElts](
int M) {
return M < (int)NumElts; }))
26484 for (
int SubVec = 0; SubVec != NumSubVecs; ++SubVec) {
26485 for (
int SubIdx = 0; SubIdx != (int)NumElts; SubIdx += NumSubElts) {
26487 std::iota(InsertionMask.begin(), InsertionMask.end(), 0);
26490 std::iota(InsertionMask.begin() + SubIdx,
26491 InsertionMask.begin() + SubIdx + NumSubElts,
26492 NumElts + (SubVec * NumSubElts));
26495 bool MatchingShuffle =
true;
26496 for (
int i = 0; i != (int)NumElts; ++i) {
26497 int ExpectIdx = InsertionMask[i];
26498 int ActualIdx =
Mask[i];
26499 if (0 <= ActualIdx && ExpectIdx != ActualIdx) {
26500 MatchingShuffle =
false;
26505 if (MatchingShuffle)
26507 RHS.getOperand(SubVec),
26515 if (
SDValue InsertN1 = ShuffleToInsert(N0, N1, Mask))
26520 if (
SDValue InsertN0 = ShuffleToInsert(N1, N0, CommuteMask))
26528 bool IsInLaneMask =
true;
26533 for (
int I = 0;
I != (int)NumElts; ++
I) {
26537 ClearMask[
I] =
M ==
I ?
I : (
I + NumElts);
26538 IsInLaneMask &= (
M ==
I) || (M == (
int)(
I + NumElts));
26540 APInt &Demanded =
M < (int)NumElts ? DemandedLHS : DemandedRHS;
26541 Demanded.
setBit(M % NumElts);
26545 if (!IsInLaneMask && (!DemandedLHS.
isZero() || !DemandedRHS.
isZero()) &&
26560 for (
int I = 0;
I != (int)NumElts; ++
I)
26562 AndMask[
I] =
Mask[
I] ==
I ? AllOnesElt : ZeroElt;
26599 EVT ScaleVT = SVT.
bitsLT(InnerSVT) ? VT : InnerVT;
26617 for (
int M : OuterMask)
26618 NewMask.
push_back(M < 0 ? -1 : InnerMask[M]);
26649 auto MergeInnerShuffle =
26656 if (OtherSVN->isSplat())
26662 for (
unsigned i = 0; i != NumElts; ++i) {
26663 int Idx = SVN->getMaskElt(i);
26671 Idx = (
Idx < (int)NumElts) ? (
Idx + NumElts) : (
Idx - NumElts);
26674 if (
Idx < (
int)NumElts) {
26677 Idx = OtherSVN->getMaskElt(
Idx);
26683 CurrentVec = (
Idx < (int)NumElts) ? OtherSVN->
getOperand(0)
26692 Mask.push_back(-1);
26699 if (!SV0.getNode() || SV0 == CurrentVec) {
26706 if (!SV1.getNode() || SV1 == CurrentVec) {
26710 Mask.push_back(
Idx + NumElts);
26716 if (
auto *CurrentSVN = dyn_cast<ShuffleVectorSDNode>(CurrentVec)) {
26717 int InnerIdx = CurrentSVN->getMaskElt(
Idx);
26718 if (InnerIdx < 0) {
26719 Mask.push_back(-1);
26722 SDValue InnerVec = (InnerIdx < (int)NumElts)
26726 Mask.push_back(-1);
26729 InnerIdx %= NumElts;
26730 if (InnerVec == SV0) {
26731 Mask.push_back(InnerIdx);
26734 if (InnerVec == SV1) {
26735 Mask.push_back(InnerIdx + NumElts);
26754 if (TLI.isShuffleMaskLegal(Mask, VT))
26759 return TLI.isShuffleMaskLegal(Mask, VT);
26771 assert(N1->getOperand(0).getValueType() == VT &&
26772 "Shuffle types don't match");
26776 bool HasSameOp0 = N0 == SV0;
26777 bool IsSV1Undef = SV1.
isUndef();
26778 if (HasSameOp0 || IsSV1Undef || N0 == SV1)
26787 cast<ShuffleVectorSDNode>(N0)->isSplat() &&
26788 !cast<ShuffleVectorSDNode>(N1)->isSplat()) {
26799 for (
int i = 0; i != 2; ++i) {
26801 N->isOnlyUserOf(
N->getOperand(i).getNode())) {
26804 auto *OtherSV = cast<ShuffleVectorSDNode>(
N->getOperand(i));
26805 assert(OtherSV->getOperand(0).getValueType() == VT &&
26806 "Shuffle types don't match");
26810 if (MergeInnerShuffle(i != 0, SVN, OtherSV,
N->getOperand(1 - i), TLI,
26818 SV1 ? SV1 : DAG.
getUNDEF(VT), Mask);
26828 if (TLI.isBinOp(SrcOpcode) &&
N->isOnlyUserOf(N0.
getNode()) &&
26830 (SrcOpcode == N1.getOpcode() &&
N->isOnlyUserOf(N1.getNode())))) {
26848 SDValue InnerN = Commute ? N1 : N0;
26849 SDValue Op0 = LeftOp ? Op00 : Op01;
26850 SDValue Op1 = LeftOp ? Op10 : Op11;
26855 auto *SVN0 = dyn_cast<ShuffleVectorSDNode>(Op0);
26857 MergeInnerShuffle(Commute, SVN, SVN0, Op1, TLI, SV0, SV1,
26859 (
llvm::any_of(SVN0->getMask(), [](
int M) { return M < 0; }) ||
26865 bool MergedLeft =
false;
26868 if (CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
false) ||
26869 CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
true)) {
26872 LeftMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
26873 LeftSV0 = Op00, LeftSV1 = Op10;
26876 bool MergedRight =
false;
26879 if (CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
false) ||
26880 CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
true)) {
26881 MergedRight =
true;
26883 RightMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
26884 RightSV0 = Op01, RightSV1 = Op11;
26887 if (MergedLeft || MergedRight) {
26890 VT,
DL, LeftSV0 ? LeftSV0 : DAG.
getUNDEF(VT),
26891 LeftSV1 ? LeftSV1 : DAG.
getUNDEF(VT), LeftMask);
26893 VT,
DL, RightSV0 ? RightSV0 : DAG.
getUNDEF(VT),
26894 RightSV1 ? RightSV1 : DAG.
getUNDEF(VT), RightMask);
26895 return DAG.
getNode(SrcOpcode,
DL, VT, LHS, RHS);
26916 EVT VT =
N->getValueType(0);
26926 unsigned Opcode =
Scalar.getOpcode();
26928 if (
Scalar.hasOneUse() &&
Scalar->getNumValues() == 1 &&
26929 TLI.isBinOp(Opcode) &&
Scalar.getValueType() == VecEltVT &&
26930 Scalar.getOperand(0).getValueType() == VecEltVT &&
26931 Scalar.getOperand(1).getValueType() == VecEltVT &&
26932 Scalar->isOnlyUserOf(
Scalar.getOperand(0).getNode()) &&
26933 Scalar->isOnlyUserOf(
Scalar.getOperand(1).getNode()) &&
26938 for (
int i : {0, 1}) {
26942 auto *
C = dyn_cast<ConstantSDNode>(
Scalar.getOperand(i ? 0 : 1));
26949 if (TLI.isShuffleMaskLegal(ShufMask, VT)) {
26964 !
Scalar.getOperand(0).getValueType().isFixedLengthVector())
26968 if (VecEltVT !=
Scalar.getValueType() &&
26974 auto *ExtIndexC = dyn_cast<ConstantSDNode>(
Scalar.getOperand(1));
26982 if (VecEltVT == SrcVT.
getScalarType() && VTNumElts <= SrcNumElts) {
26985 Mask[0] = ExtIndexC->getZExtValue();
26986 SDValue LegalShuffle = TLI.buildLegalVectorShuffle(
26993 return LegalShuffle;
26996 if (VTNumElts != SrcNumElts) {
27009 EVT VT =
N->getValueType(0);
27013 uint64_t InsIdx =
N->getConstantOperandVal(2);
27113 if ((N0.
isUndef() || N0SrcSVT == N1SrcSVT) &&
27125 }
else if ((N1SrcSVT.
getSizeInBits() % EltSizeInBits) == 0) {
27148 if (InsIdx < OtherIdx) {
27152 AddToWorklist(NewOp.
getNode());
27166 Ops[InsIdx / Factor] = N1;
27188 auto Op =
N->getOpcode();
27190 "opcode should be FP16_TO_FP or BF16_TO_FP.");
27206 N->getValueType(0), {N0});
27222 return visitFP16_TO_FP(
N);
27228 unsigned Opcode =
N->getOpcode();
27246 if (!TLI.isOperationLegalOrCustom(Opcode, VT) &&
27247 TLI.isOperationLegalOrCustom(NewOpcode, VT) &&
27249 return DAG.
getNode(NewOpcode,
SDLoc(
N),
N->getValueType(0), N0);
27262 return DAG.
getNode(Opcode,
SDLoc(
N),
N->getValueType(0), Subvec);
27285 if (
SDValue Fused = visitFSUBForFMACombine<VPMatchContext>(
N)) {
27286 AddToWorklist(Fused.getNode());
27294 if (
N->getOpcode() == ISD::VP_GATHER)
27295 if (
SDValue SD = visitVPGATHER(
N))
27298 if (
N->getOpcode() == ISD::VP_SCATTER)
27299 if (
SDValue SD = visitVPSCATTER(
N))
27302 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_LOAD)
27303 if (
SDValue SD = visitVP_STRIDED_LOAD(
N))
27306 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_STORE)
27307 if (
SDValue SD = visitVP_STRIDED_STORE(
N))
27313 bool AreAllEltsDisabled =
false;
27317 AreAllEltsDisabled |=
27321 if (!AreAllEltsDisabled) {
27322 switch (
N->getOpcode()) {
27324 return visitVP_FADD(
N);
27326 return visitVP_FSUB(
N);
27328 return visitFMA<VPMatchContext>(
N);
27329 case ISD::VP_SELECT:
27330 return visitVP_SELECT(
N);
27332 return visitMUL<VPMatchContext>(
N);
27334 return foldSubCtlzNot<VPMatchContext>(
N, DAG);
27343 return DAG.
getUNDEF(
N->getValueType(0));
27347 if (
const auto *MemSD = dyn_cast<MemSDNode>(
N)) {
27348 if (MemSD->writeMem())
27349 return MemSD->getChain();
27350 return CombineTo(
N, DAG.
getUNDEF(
N->getValueType(0)), MemSD->getChain());
27355 return N->getOperand(0);
27363 EVT MemVT = cast<FPStateAccessSDNode>(
N)->getMemoryVT();
27368 for (
auto *U :
Ptr->users()) {
27371 if (
auto *Ld = dyn_cast<LoadSDNode>(U)) {
27372 if (LdNode && LdNode != Ld)
27387 if (
U.getResNo() == 0) {
27388 if (
auto *St = dyn_cast<StoreSDNode>(
U.getUser())) {
27406 CombineTo(StNode, Res,
false);
27413 EVT MemVT = cast<FPStateAccessSDNode>(
N)->getMemoryVT();
27417 for (
auto *U :
Ptr->users()) {
27420 if (
auto *St = dyn_cast<StoreSDNode>(U)) {
27421 if (StNode && StNode != St)
27436 auto *LdNode = dyn_cast<LoadSDNode>(StValue);
27457 EVT VT =
N->getValueType(0);
27464 if (LegalOperations)
27470 EVT RVT =
RHS.getValueType();
27471 unsigned NumElts =
RHS.getNumOperands();
27476 auto BuildClearMask = [&](
int Split) {
27477 int NumSubElts = NumElts *
Split;
27481 for (
int i = 0; i != NumSubElts; ++i) {
27482 int EltIdx = i /
Split;
27483 int SubIdx = i %
Split;
27493 if (
auto *Cst = dyn_cast<ConstantSDNode>(Elt))
27494 Bits = Cst->getAPIntValue();
27495 else if (
auto *CstFP = dyn_cast<ConstantFPSDNode>(Elt))
27502 Bits =
Bits.extractBits(NumSubBits, (Split - SubIdx - 1) * NumSubBits);
27504 Bits =
Bits.extractBits(NumSubBits, SubIdx * NumSubBits);
27506 if (
Bits.isAllOnes())
27508 else if (Bits == 0)
27517 if (!TLI.isVectorClearMaskLegal(Indices, ClearVT))
27531 for (
int Split = 1;
Split <= MaxSplit; ++
Split)
27533 if (
SDValue S = BuildClearMask(Split))
27542 const SDLoc &
DL,
bool LegalTypes) {
27545 unsigned Opcode =
N->getOpcode();
27546 EVT VT =
N->getValueType(0);
27553 int Index0, Index1;
27560 if (!Src0 || !Src1 || Index0 != Index1 ||
27587 for (
auto [
X,
Y] :
zip(EltsX, EltsY))
27603 EVT VT =
N->getValueType(0);
27604 assert(VT.
isVector() &&
"SimplifyVCastOp only works on vectors!");
27606 unsigned Opcode =
N->getOpcode();
27636 EVT VT =
N->getValueType(0);
27637 assert(VT.
isVector() &&
"SimplifyVBinOp only works on vectors!");
27641 unsigned Opcode =
N->getOpcode();
27652 auto *Shuf0 = dyn_cast<ShuffleVectorSDNode>(LHS);
27653 auto *Shuf1 = dyn_cast<ShuffleVectorSDNode>(RHS);
27654 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
27655 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
27658 RHS.getOperand(0), Flags);
27670 Shuf0->hasOneUse() && Shuf0->getOperand(1).isUndef() &&
27679 Shuf1->hasOneUse() && Shuf1->getOperand(1).isUndef() &&
27695 LHS.getOperand(2) ==
RHS.getOperand(2) &&
27700 EVT NarrowVT =
X.getValueType();
27701 if (NarrowVT ==
Y.getValueType() &&
27703 LegalOperations)) {
27716 return Op.isUndef() ||
27717 ISD::isBuildVectorOfConstantSDNodes(Op.getNode());
27726 if (ConcatWithConstantOrUndef(LHS) && ConcatWithConstantOrUndef(RHS) &&
27728 EVT NarrowVT =
LHS.getOperand(0).getValueType();
27729 if (NarrowVT ==
RHS.getOperand(0).getValueType() &&
27731 unsigned NumOperands =
LHS.getNumOperands();
27733 for (
unsigned i = 0; i != NumOperands; ++i) {
27736 RHS.getOperand(i)));
27752 "First argument must be a SetCC node!");
27755 cast<CondCodeSDNode>(N0.
getOperand(2))->get());
27760 if (
SCC.getNode()) {
27767 SCC.getOperand(0),
SCC.getOperand(1),
27768 SCC.getOperand(4), Flags);
27769 AddToWorklist(
SETCC.getNode());
27771 SCC.getOperand(2),
SCC.getOperand(3));
27786bool DAGCombiner::SimplifySelectOps(
SDNode *TheSelect,
SDValue LHS,
27799 CC = cast<CondCodeSDNode>(TheSelect->
getOperand(4))->get();
27806 CC = cast<CondCodeSDNode>(
Cmp.getOperand(2))->get();
27807 CmpLHS =
Cmp.getOperand(0);
27811 if (Zero &&
Zero->isZero() &&
27815 CombineTo(TheSelect, Sqrt);
27825 if (
LHS.getOpcode() !=
RHS.getOpcode() ||
27838 if (
LHS.getOperand(0) !=
RHS.getOperand(0) ||
27882 Visited.
insert(TheSelect);
27961 CombineTo(TheSelect, Load);
27965 CombineTo(
LHS.getNode(),
Load.getValue(0),
Load.getValue(1));
27966 CombineTo(
RHS.getNode(),
Load.getValue(0),
Load.getValue(1));
28006 auto *N2C = dyn_cast<ConstantSDNode>(N2.
getNode());
28007 if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue() - 1)) == 0)) {
28008 unsigned ShCt = XType.
getSizeInBits() - N2C->getAPIntValue().logBase2() - 1;
28012 AddToWorklist(Shift.
getNode());
28014 if (XType.
bitsGT(AType)) {
28016 AddToWorklist(Shift.
getNode());
28020 Shift = DAG.
getNOT(
DL, Shift, AType);
28032 AddToWorklist(Shift.
getNode());
28034 if (XType.
bitsGT(AType)) {
28036 AddToWorklist(Shift.
getNode());
28040 Shift = DAG.
getNOT(
DL, Shift, AType);
28103 EVT VT =
N->getValueType(0);
28111 EVT IntVT =
Int.getValueType();
28125 SignMask = ~SignMask;
28131 SignMask = ~SignMask;
28136 AddToWorklist(
Int.getNode());
28144SDValue DAGCombiner::convertSelectOfFPConstantsToLoadOffset(
28152 auto *TV = dyn_cast<ConstantFPSDNode>(N2);
28153 auto *FV = dyn_cast<ConstantFPSDNode>(N3);
28160 TLI.
isFPImmLegal(TV->getValueAPF(), TV->getValueType(0), ForCodeSize) ||
28161 TLI.
isFPImmLegal(FV->getValueAPF(), FV->getValueType(0), ForCodeSize))
28166 if (!TV->hasOneUse() && !FV->hasOneUse())
28170 const_cast<ConstantFP*
>(TV->getConstantFPValue()) };
28178 Align Alignment = cast<ConstantPoolSDNode>(CPIdx)->getAlign();
28187 AddToWorklist(
Cond.getNode());
28189 AddToWorklist(CstOffset.
getNode());
28191 AddToWorklist(CPIdx.
getNode());
28201 bool NotExtCompare) {
28203 if (N2 == N3)
return N2;
28208 auto *N1C = dyn_cast<ConstantSDNode>(N1.
getNode());
28209 auto *N2C = dyn_cast<ConstantSDNode>(N2.
getNode());
28210 auto *N3C = dyn_cast<ConstantSDNode>(N3.
getNode());
28214 AddToWorklist(
SCC.getNode());
28215 if (
auto *SCCC = dyn_cast<ConstantSDNode>(SCC)) {
28218 return !(SCCC->isZero()) ? N2 : N3;
28223 convertSelectOfFPConstantsToLoadOffset(
DL, N0, N1, N2, N3,
CC))
28226 if (
SDValue V = foldSelectCCToShiftAnd(
DL, N0, N1, N2, N3,
CC))
28238 auto *ConstAndRHS = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
28239 if (ConstAndRHS && ConstAndRHS->getAPIntValue().popcount() == 1) {
28241 const APInt &AndMask = ConstAndRHS->getAPIntValue();
28259 bool Fold = N2C &&
isNullConstant(N3) && N2C->getAPIntValue().isPowerOf2();
28260 bool Swap = N3C &&
isNullConstant(N2) && N3C->getAPIntValue().isPowerOf2();
28262 if ((Fold || Swap) &&
28274 if (NotExtCompare && N2C->isOne())
28287 AddToWorklist(
SCC.getNode());
28288 AddToWorklist(Temp.
getNode());
28293 unsigned ShCt = N2C->getAPIntValue().logBase2();
28318 if (
auto *ValueOnZeroC = dyn_cast<ConstantSDNode>(ValueOnZero)) {
28340 if (!NotExtCompare && N1C && N2C && N3C &&
28341 N2C->getAPIntValue() == ~N3C->getAPIntValue() &&
28356 if (
SDValue ABD = foldSelectToABD(N0, N1, N2, N3,
CC,
DL))
28365 bool foldBooleans) {
28367 DagCombineInfo(DAG, Level,
false,
this);
28465 bool AssumeNonZero) {
28468 auto PeekThroughCastsAndTrunc = [](
SDValue V) {
28470 switch (V.getOpcode()) {
28473 V = V.getOperand(0);
28484 Op = PeekThroughCastsAndTrunc(
Op);
28490 if (
C->isZero() ||
C->isOpaque())
28493 if (
C->getAPIntValue().isPowerOf2()) {
28509 for (
const APInt &Pow2 : Pow2Constants)
28518 auto CastToVT = [&](
EVT NewVT,
SDValue ToCast) {
28519 ToCast = PeekThroughCastsAndTrunc(ToCast);
28520 EVT CurVT = ToCast.getValueType();
28521 if (NewVT == CurVT)
28533 if (AssumeNonZero ||
Op->getFlags().hasNoUnsignedWrap() ||
28536 Depth + 1, AssumeNonZero))
28538 CastToVT(VT,
Op.getOperand(1)));
28545 Depth + 1, AssumeNonZero))
28547 Depth + 1, AssumeNonZero))
28548 return DAG.
getSelect(
DL, VT,
Op.getOperand(0), LogX, LogY);
28563 return DAG.
getNode(
Op.getOpcode(),
DL, VT, LogX, LogY);
28572 bool KnownNonZero,
bool InexpensiveOnly,
28573 std::optional<EVT> OutVT) {
28574 EVT VT = OutVT ? *OutVT :
V.getValueType();
28575 SDValue InexpensiveLogBase2 =
28578 return InexpensiveLogBase2;
28600 EVT VT =
Op.getValueType();
28608 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
28615 AddToWorklist(Est.getNode());
28623 for (
int i = 0; i < Iterations; ++i) {
28626 if (i == Iterations - 1) {
28628 AddToWorklist(MulEst.
getNode());
28632 AddToWorklist(NewEst.
getNode());
28635 (i == Iterations - 1 ?
N : FPOne), NewEst, Flags);
28636 AddToWorklist(NewEst.
getNode());
28639 AddToWorklist(NewEst.
getNode());
28642 AddToWorklist(Est.getNode());
28647 AddToWorklist(Est.getNode());
28663 unsigned Iterations,
28675 for (
unsigned i = 0; i < Iterations; ++i) {
28695 unsigned Iterations,
28708 for (
unsigned i = 0; i < Iterations; ++i) {
28717 if (Reciprocal || (i + 1) < Iterations) {
28740 EVT VT =
Op.getValueType();
28748 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
28755 bool UseOneConstNR =
false;
28759 AddToWorklist(Est.
getNode());
28761 if (Iterations > 0)
28762 Est = UseOneConstNR
28763 ? buildSqrtNROneConst(
Op, Est, Iterations, Flags, Reciprocal)
28764 : buildSqrtNRTwoConst(
Op, Est, Iterations,
Flags, Reciprocal);
28784 return buildSqrtEstimateImpl(
Op, Flags,
true);
28788 return buildSqrtEstimateImpl(
Op, Flags,
false);
28792bool DAGCombiner::mayAlias(
SDNode *Op0,
SDNode *Op1)
const {
28794 struct MemUseCharacteristics {
28803 auto getCharacteristics = [](
SDNode *
N) -> MemUseCharacteristics {
28804 if (
const auto *LSN = dyn_cast<LSBaseSDNode>(
N)) {
28806 if (
auto *
C = dyn_cast<ConstantSDNode>(LSN->getOffset()))
28809 ? -1 *
C->getSExtValue()
28812 return {LSN->isVolatile(), LSN->isAtomic(),
28813 LSN->getBasePtr(),
Offset ,
28816 if (
const auto *LN = cast<LifetimeSDNode>(
N))
28820 (LN->hasOffset()) ? LN->getOffset() : 0,
28833 MemUseCharacteristics MUC0 = getCharacteristics(Op0),
28834 MUC1 = getCharacteristics(Op1);
28837 if (MUC0.BasePtr.getNode() && MUC0.BasePtr == MUC1.BasePtr &&
28838 MUC0.Offset == MUC1.Offset)
28842 if (MUC0.IsVolatile && MUC1.IsVolatile)
28847 if (MUC0.IsAtomic && MUC1.IsAtomic)
28850 if (MUC0.MMO && MUC1.MMO) {
28851 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
28852 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
28858 if ((MUC0.NumBytes.hasValue() && MUC0.NumBytes.isScalable() &&
28859 MUC0.Offset != 0) ||
28860 (MUC1.NumBytes.hasValue() && MUC1.NumBytes.isScalable() &&
28872 if (!MUC0.MMO || !MUC1.MMO)
28878 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
28879 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
28887 int64_t SrcValOffset0 = MUC0.MMO->getOffset();
28888 int64_t SrcValOffset1 = MUC1.MMO->getOffset();
28889 Align OrigAlignment0 = MUC0.MMO->getBaseAlign();
28890 Align OrigAlignment1 = MUC1.MMO->getBaseAlign();
28894 if (OrigAlignment0 == OrigAlignment1 && SrcValOffset0 != SrcValOffset1 &&
28900 int64_t OffAlign0 = SrcValOffset0 % OrigAlignment0.
value();
28901 int64_t OffAlign1 = SrcValOffset1 % OrigAlignment1.
value();
28905 if ((OffAlign0 +
static_cast<int64_t
>(
28907 (OffAlign1 +
static_cast<int64_t
>(
28921 if (
UseAA && AA && MUC0.MMO->getValue() && MUC1.MMO->getValue() &&
28924 (!Size0.
isScalable() || SrcValOffset0 == 0) &&
28925 (!Size1.
isScalable() || SrcValOffset1 == 0)) {
28927 int64_t MinOffset = std::min(SrcValOffset0, SrcValOffset1);
28950void DAGCombiner::GatherAllAliases(
SDNode *
N,
SDValue OriginalChain,
28957 const bool IsLoad = isa<LoadSDNode>(
N) && cast<LoadSDNode>(
N)->isSimple();
28961 unsigned Depth = 0;
28964 auto ImproveChain = [&](
SDValue &
C) ->
bool {
28965 switch (
C.getOpcode()) {
28974 bool IsOpLoad = isa<LoadSDNode>(
C.getNode()) &&
28975 cast<LSBaseSDNode>(
C.getNode())->isSimple();
28976 if ((IsLoad && IsOpLoad) || !
mayAlias(
N,
C.getNode())) {
28978 C =
C.getOperand(0);
28987 C =
C.getOperand(0);
28996 C =
C.getOperand(0);
29009 while (!Chains.
empty()) {
29043 if (ImproveChain(Chain)) {
29065 GatherAllAliases(
N, OldChain, Aliases);
29068 if (Aliases.
empty())
29072 if (Aliases.
size() == 1)
29092bool DAGCombiner::parallelizeChainedStores(
StoreSDNode *St) {
29109 if (!
BasePtr.getBase().getNode())
29113 if (
BasePtr.getBase().isUndef())
29131 if (Chain->getMemoryVT().isScalableVector())
29135 if (!
SDValue(Chain, 0)->hasOneUse())
29138 if (!Chain->isSimple() || Chain->isIndexed())
29147 int64_t
Length = (Chain->getMemoryVT().getSizeInBits() + 7) / 8;
29150 auto I = Intervals.find(
Offset);
29155 if (
I != Intervals.begin() && (--
I).stop() <=
Offset)
29164 if (ChainedStores.
empty())
29171 for (
unsigned I = ChainedStores.
size();
I;) {
29173 SDValue BetterChain = FindBetterChain(S, NewChain);
29177 ChainedStores[
I] = S;
29181 SDValue BetterChain = FindBetterChain(St, NewChain);
29196 auto hasImprovedChain = [&](
SDValue ST) ->
bool {
29197 return ST->getOperand(0) != NewChain;
29199 bool AddNewChain =
llvm::all_of(TFOps, hasImprovedChain);
29209 AddToWorklist(
Op.getNode());
29210 AddToWorklist(STChain);
29214bool DAGCombiner::findBetterNeighborChains(
StoreSDNode *St) {
29221 if (!
BasePtr.getBase().getNode())
29225 if (
BasePtr.getBase().isUndef())
29229 if (parallelizeChainedStores(St))
29234 if (St->
getChain() != BetterChain) {
29235 replaceStoreChain(St, BetterChain);
29245 DAGCombiner(*
this, AA, 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)
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-...
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.
void Combine(CombineLevel Level, AAResults *AA, CodeGenOptLevel OptLevel)
This iterates over the nodes in the SelectionDAG, folding certain types of nodes together,...
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...