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) {
15773 if (
Op.getOpcode() ==
ISD::BITCAST &&
Op.getOperand(0).getValueType() == 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 cast<CondCodeSDNode>(Vec->
getOperand(2))->get());
22842 return DAG.
getNode(Opc,
DL, ResVT, Op0, Op1);
22854bool DAGCombiner::refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
22871 auto *IndexC = dyn_cast<ConstantSDNode>(
N->getOperand(1));
22876 "Original ISD::EXTRACT_VECTOR_ELT is undefinend?");
22880 EVT ScalarVT =
N->getValueType(0);
22896 Entry(Entry &&) =
default;
22897 Entry(
SDNode *Producer_,
unsigned BitPos_,
int NumBits_)
22898 :
Producer(Producer_), BitPos(BitPos_), NumBits(NumBits_) {}
22901 Entry(
const Entry &) =
delete;
22902 Entry &operator=(
const Entry &) =
delete;
22903 Entry &operator=(Entry &&) =
delete;
22909 Worklist.
emplace_back(
N, VecEltBitWidth * IndexC->getZExtValue(),
22912 while (!Worklist.
empty()) {
22919 bool ProducerIsLeaf =
false;
22922 switch (
User->getOpcode()) {
22930 User->getValueSizeInBits(0));
22936 if (
auto *ShAmtC = dyn_cast<ConstantSDNode>(
User->
getOperand(1));
22940 unsigned ShAmt = ShAmtC->getZExtValue();
22948 ProducerIsLeaf =
true;
22956 if (ProducerIsLeaf)
22960 unsigned NewVecEltBitWidth = Leafs.
front().NumBits;
22963 if (NewVecEltBitWidth == VecEltBitWidth)
22973 if (!
all_of(Leafs, [NewVecEltBitWidth](
const Entry &E) {
22974 return (
unsigned)E.NumBits == NewVecEltBitWidth &&
22975 E.Producer->getValueSizeInBits(0) == NewVecEltBitWidth &&
22976 E.BitPos % NewVecEltBitWidth == 0;
22988 if (LegalOperations &&
22994 for (
const Entry &E : Leafs) {
22996 unsigned NewIndex = E.BitPos / NewVecEltBitWidth;
22998 "Creating out-of-bounds ISD::EXTRACT_VECTOR_ELT?");
23001 CombineTo(E.Producer, V);
23010 EVT ScalarVT =
N->getValueType(0);
23023 AddUsersToWorklist(VecOp.
getNode());
23047 auto *IndexC = dyn_cast<ConstantSDNode>(Index);
23058 "BUILD_VECTOR used for scalable vectors");
23059 unsigned IndexVal =
23067 if (ScalarVT == InEltVT)
23107 unsigned ExtractIndex = IndexC->getZExtValue();
23109 unsigned BCTruncElt = IsLE ? 0 : NumElts - 1;
23122 EVT XVT =
X.getValueType();
23124 "Extract element and scalar to vector can't change element type "
23125 "from FP to integer.");
23126 unsigned XBitWidth =
X.getValueSizeInBits();
23127 unsigned Scale = XBitWidth / VecEltBitWidth;
23128 BCTruncElt = IsLE ? 0 : Scale - 1;
23133 if (ExtractIndex < Scale && XBitWidth > VecEltBitWidth) {
23134 assert(XBitWidth % VecEltBitWidth == 0 &&
23135 "Scalar bitwidth must be a multiple of vector element bitwidth");
23137 if (ExtractIndex != BCTruncElt) {
23138 unsigned ShiftIndex =
23139 IsLE ? ExtractIndex : (Scale - 1) - ExtractIndex;
23157 auto *Shuf = cast<ShuffleVectorSDNode>(VecOp);
23159 int OrigElt = Shuf->getMaskElt(IndexC->getZExtValue());
23167 if (OrigElt < (
int)NumElts) {
23171 OrigElt -= NumElts;
23187 if (!LegalOperations ||
23199 return Use->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
23200 Use->getOperand(0) == VecOp &&
23201 isa<ConstantSDNode>(Use->getOperand(1));
23206 if (CstElt->getAPIntValue().ult(NumElts))
23207 DemandedElts.
setBit(CstElt->getZExtValue());
23226 if (refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
N))
23232 bool BCNumEltsChanged =
false;
23247 BCNumEltsChanged =
true;
23253 if (!LegalOperations && !IndexC && VecOp.
hasOneUse() &&
23256 auto *
VecLoad = dyn_cast<LoadSDNode>(VecOp);
23257 if (VecLoad &&
VecLoad->isSimple())
23258 return scalarizeExtractedVectorLoad(
N, VecVT, Index, VecLoad);
23263 if (!LegalOperations || !IndexC)
23269 int Elt = IndexC->getZExtValue();
23272 LN0 = cast<LoadSDNode>(VecOp);
23280 LN0 = cast<LoadSDNode>(VecOp.
getOperand(0));
23282 if (
auto *Shuf = dyn_cast<ShuffleVectorSDNode>(VecOp)) {
23293 if (BCNumEltsChanged)
23297 int Idx = (Elt > (int)NumElts) ? -1 : Shuf->getMaskElt(Elt);
23308 LN0 = cast<LoadSDNode>(VecOp);
23309 Elt = (
Idx < (int)NumElts) ?
Idx :
Idx - (int)NumElts;
23328 Index.getValueType());
23346 return scalarizeExtractedVectorLoad(
N, VecVT, Index, LN0);
23360 unsigned NumInScalars =
N->getNumOperands();
23362 EVT VT =
N->getValueType(0);
23369 EVT SourceType = MVT::Other;
23370 bool AllAnyExt =
true;
23372 for (
unsigned i = 0; i != NumInScalars; ++i) {
23375 if (
In.isUndef())
continue;
23381 if (!ZeroExt && !AnyExt) {
23382 SourceType = MVT::Other;
23387 EVT InTy =
In.getOperand(0).getValueType();
23390 if (SourceType == MVT::Other)
23393 else if (InTy != SourceType) {
23395 SourceType = MVT::Other;
23400 AllAnyExt &= AnyExt;
23408 SourceType != MVT::Other &&
23409 llvm::has_single_bit<uint32_t>(OutScalarTy.
getSizeInBits()) &&
23410 llvm::has_single_bit<uint32_t>(SourceType.
getSizeInBits());
23424 assert(ElemRatio > 1 &&
"Invalid element size ratio");
23432 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
23436 Cast.
isUndef()) &&
"Invalid cast opcode");
23442 unsigned Index = isLE ? (i * ElemRatio) :
23443 (i * ElemRatio + (ElemRatio - 1));
23445 assert(Index < Ops.size() &&
"Invalid index");
23452 "Invalid vector size");
23475 EVT VT =
N->getValueType(0);
23494 unsigned NumInScalars =
N->getNumOperands();
23497 auto PeekThroughBitcast = [](
SDValue Op) {
23499 return Op.getOperand(0);
23505 for (
unsigned i = 0; i != NumInScalars; ++i) {
23506 SDValue In = PeekThroughBitcast(
N->getOperand(i));
23508 if (
In.isUndef())
continue;
23513 In = PeekThroughBitcast(
In.getOperand(0));
23524 SDValue part = PeekThroughBitcast(
In.getOperand(0));
23528 }
else if (Src != part) {
23533 SDValue ShiftAmtVal =
In.getOperand(1);
23534 if (!isa<ConstantSDNode>(ShiftAmtVal))
23537 uint64_t ShiftAmt =
In.getConstantOperandVal(1);
23540 if (ShiftAmt != i * ScalarTypeBitsize)
23546 if (!Src || Src.getValueType().getSizeInBits() != VT.
getSizeInBits())
23555 unsigned LeftIdx,
bool DidSplitVec) {
23558 EVT VT =
N->getValueType(0);
23563 unsigned ShuffleNumElems = NumElems;
23573 assert(InVT2Size <= InVT1Size &&
23574 "Inputs must be sorted to be in non-increasing vector size order.");
23578 if (InVT1 != VT || InVT2 != VT) {
23579 if ((VTSize % InVT1Size == 0) && InVT1 == InVT2) {
23582 unsigned NumConcats = VTSize / InVT1Size;
23583 assert(NumConcats >= 2 &&
"Concat needs at least two inputs!");
23585 ConcatOps[0] = VecIn1;
23586 ConcatOps[1] = VecIn2 ? VecIn2 : DAG.
getUNDEF(InVT1);
23589 }
else if (InVT1Size == VTSize * 2) {
23601 Vec2Offset = NumElems;
23603 assert(InVT2Size <= InVT1Size &&
23604 "Second input is not going to be larger than the first one.");
23610 if (LegalOperations &&
23617 if (InVT1 != InVT2) {
23621 DAG.
getUNDEF(InVT1), VecIn2, ZeroIdx);
23623 ShuffleNumElems = NumElems * 2;
23625 }
else if (InVT2Size * 2 == VTSize && InVT1Size == VTSize) {
23627 ConcatOps[0] = VecIn2;
23629 }
else if (InVT1Size / VTSize > 1 && InVT1Size % VTSize == 0) {
23637 assert(InVT2Size <= InVT1Size &&
23638 "Second input is not going to be larger than the first one.");
23647 if (InVT1 != InVT2) {
23649 DAG.
getUNDEF(InVT1), VecIn2, ZeroIdx);
23651 ShuffleNumElems = InVT1Size / VTSize * NumElems;
23667 for (
unsigned i = 0; i != NumElems; ++i) {
23668 if (VectorMask[i] <= 0)
23671 unsigned ExtIndex =
N->getOperand(i).getConstantOperandVal(1);
23672 if (VectorMask[i] == (
int)LeftIdx) {
23673 Mask[i] = ExtIndex;
23674 }
else if (VectorMask[i] == (
int)LeftIdx + 1) {
23675 Mask[i] = Vec2Offset + ExtIndex;
23688 if (ShuffleNumElems > NumElems)
23701 for (
int i = 0; i != NumBVOps; ++i) {
23733 if (DestSize % SrcSize != 0 ||
23739 int ZextRatio = DestSize / SrcSize;
23740 int NumMaskElts = NumBVOps * ZextRatio;
23742 for (
int i = 0; i != NumMaskElts; ++i) {
23743 if (i / ZextRatio == ZextElt) {
23764 ZeroVec, ShufMask, DAG);
23771template <
typename R,
typename T>
23775 return static_cast<decltype(std::distance(
Range.begin(),
I))
>(-1);
23776 return std::distance(
Range.begin(),
I);
23784 EVT VT =
N->getValueType(0);
23797 bool UsesZeroVector =
false;
23798 unsigned NumElems =
N->getNumOperands();
23810 for (
unsigned i = 0; i != NumElems; ++i) {
23820 UsesZeroVector =
true;
23828 !isa<ConstantSDNode>(
Op.getOperand(1)))
23830 SDValue ExtractedFromVec =
Op.getOperand(0);
23835 const APInt &ExtractIdx =
Op.getConstantOperandAPInt(1);
23853 VectorMask[i] =
Idx;
23857 if (VecIn.
size() < 2)
23864 bool DidSplitVec =
false;
23865 if (VecIn.
size() == 2) {
23866 unsigned MaxIndex = 0;
23867 unsigned NearestPow2 = 0;
23872 for (
unsigned i = 0; i < NumElems; i++) {
23873 if (VectorMask[i] <= 0)
23875 unsigned Index =
N->getOperand(i).getConstantOperandVal(1);
23876 IndexVec[i] =
Index;
23877 MaxIndex = std::max(MaxIndex, Index);
23881 if (InVT.
isSimple() && NearestPow2 > 2 && MaxIndex < NearestPow2 &&
23882 NumElems * 2 < NearestPow2) {
23883 unsigned SplitSize = NearestPow2 / 2;
23896 DidSplitVec =
true;
23898 for (
unsigned i = 0; i < NumElems; i++) {
23899 if (VectorMask[i] <= 0)
23901 VectorMask[i] = (IndexVec[i] < SplitSize) ? 1 : 2;
23914 b.getValueType().getVectorNumElements();
23919 for (
int &SourceVectorIndex : VectorMask) {
23920 if (SourceVectorIndex <= 0)
23924 VecIn[SourceVectorIndex] == SortedVecIn[
Idx] &&
"Remapping failure");
23925 SourceVectorIndex =
Idx;
23928 VecIn = std::move(SortedVecIn);
23946 for (
unsigned In = 0, Len = (VecIn.
size() / 2); In < Len; ++In) {
23947 unsigned LeftIdx = 2 *
In + 1;
23948 SDValue VecLeft = VecIn[LeftIdx];
23950 (LeftIdx + 1) < VecIn.
size() ? VecIn[LeftIdx + 1] :
SDValue();
23952 if (
SDValue Shuffle = createBuildVecShuffle(
DL,
N, VectorMask, VecLeft,
23953 VecRight, LeftIdx, DidSplitVec))
23961 if (UsesZeroVector)
23966 if (Shuffles.
size() == 1)
23967 return Shuffles[0];
23970 for (
int &Vec : VectorMask)
23972 Vec = Shuffles.
size() - 1;
23974 Vec = (Vec - 1) / 2;
23988 if (Shuffles.
size() % 2)
23991 for (
unsigned CurSize = Shuffles.
size(); CurSize > 1; CurSize /= 2) {
23993 Shuffles[CurSize] = DAG.
getUNDEF(VT);
23996 for (
unsigned In = 0, Len = CurSize / 2;
In <
Len; ++
In) {
24003 L.use_empty() &&
L.getOperand(1).isUndef() &&
24004 L.getOperand(0).getValueType() ==
L.getValueType();
24005 if (IsLeftShuffle) {
24006 LMask = cast<ShuffleVectorSDNode>(
L.getNode())->getMask();
24007 L =
L.getOperand(0);
24012 R.use_empty() &&
R.getOperand(1).isUndef() &&
24013 R.getOperand(0).getValueType() ==
R.getValueType();
24014 if (IsRightShuffle) {
24015 RMask = cast<ShuffleVectorSDNode>(
R.getNode())->getMask();
24016 R =
R.getOperand(0);
24018 for (
unsigned I = 0;
I != NumElems; ++
I) {
24019 if (VectorMask[
I] ==
Left) {
24023 VectorMask[
I] =
In;
24024 }
else if (VectorMask[
I] ==
Right) {
24026 if (IsRightShuffle)
24027 Mask[
I] = RMask[
I] + NumElems;
24028 VectorMask[
I] =
In;
24035 return Shuffles[0];
24043 if (LegalOperations)
24046 EVT VT =
N->getValueType(0);
24048 bool FoundZeroExtend =
false;
24050 auto checkElem = [&](
SDValue Op) -> int64_t {
24051 unsigned Opc =
Op.getOpcode();
24056 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op.getOperand(0).getOperand(1)))
24057 return C->getZExtValue();
24065 int64_t
Offset = checkElem(Op0);
24069 unsigned NumElems =
N->getNumOperands();
24071 EVT InSVT =
In.getValueType().getScalarType();
24079 for (
unsigned i = 1; i != NumElems; ++i) {
24080 if ((
Offset + i) != checkElem(
N->getOperand(i)))
24098SDValue DAGCombiner::convertBuildVecZextToBuildVecWithZeros(
SDNode *
N) {
24107 EVT VT =
N->getValueType(0);
24108 EVT OpVT =
N->getOperand(0).getValueType();
24122 unsigned ActiveBits = 0;
24127 if (
auto *Cst = dyn_cast<ConstantSDNode>(
Op)) {
24128 unsigned OpActiveBits =
24129 Cst->getAPIntValue().trunc(EltBitwidth).getActiveBits();
24130 if (OpActiveBits == 0) {
24131 KnownZeroOps.setBit(
I.index());
24139 if (
I.index() != 0)
24145 unsigned CurrActiveBits =
24146 Op.getOperand(0).getValueSizeInBits().getFixedValue();
24147 assert(!ActiveBits &&
"Already encountered non-constant-zero operand?");
24148 ActiveBits = CurrActiveBits;
24150 if (2 * ActiveBits > EltBitwidth)
24155 if (ActiveBits == 0)
24160 EVT NewScalarIntVT, NewIntVT;
24161 std::optional<unsigned> Factor;
24166 assert(2 * ActiveBits <= EltBitwidth &&
24167 "We know that half or less bits of the element are active.");
24168 for (
unsigned Scale = EltBitwidth / ActiveBits; Scale >= 2; --Scale) {
24169 if (EltBitwidth % Scale != 0)
24171 unsigned ChunkBitwidth = EltBitwidth / Scale;
24172 assert(ChunkBitwidth >= ActiveBits &&
"As per starting point.");
24175 Scale *
N->getNumOperands());
24177 (LegalOperations &&
24195 assert(!
Op.isUndef() &&
"FIXME: after allowing UNDEF's, handle them here.");
24196 unsigned SrcOpIdx =
I.index();
24197 if (KnownZeroOps[SrcOpIdx]) {
24198 NewOps.
append(*Factor, ZeroOp);
24204 NewOps.
append(*Factor - 1, ZeroOp);
24213 EVT VT =
N->getValueType(0);
24227 if (!LegalOperations) {
24228 SDValue Splat = cast<BuildVectorSDNode>(
N)->getSplatValue();
24249 if (!LegalTypes && (
N->getNumOperands() > 1)) {
24254 if (
auto CNode = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
24259 int Offset = checkElem(Op0);
24260 for (
unsigned i = 0; i <
N->getNumOperands(); ++i) {
24261 if (
Offset + i != checkElem(
N->getOperand(i))) {
24271 ((
Offset %
N->getValueType(0).getVectorNumElements()) ==
24277 if (
SDValue V = convertBuildVecZextToZext(
N))
24280 if (
SDValue V = convertBuildVecZextToBuildVecWithZeros(
N))
24283 if (
SDValue V = reduceBuildVecExtToExtBuildVec(
N))
24286 if (
SDValue V = reduceBuildVecTruncToBitCast(
N))
24289 if (
SDValue V = reduceBuildVecToShuffle(
N))
24296 assert(!
V.isUndef() &&
"Splat of undef should have been handled earlier");
24305 EVT OpVT =
N->getOperand(0).getValueType();
24312 EVT VT =
N->getValueType(0);
24321 !
Op.getOperand(0).getValueType().isVector())
24330 EVT LastOpVT = Ops.
back().getValueType();
24332 AnyFPVT = LastOpVT;
24340 if (AnyFPVT !=
EVT()) {
24343 if (
Op.getValueType() == SVT)
24362 EVT VT =
N->getValueType(0);
24372 if (!FirstConcat) {
24373 SubVT =
Op.getOperand(0).getValueType();
24379 if (SubVT !=
Op.getOperand(0).getValueType())
24382 assert(FirstConcat &&
"Concat of all-undefs found");
24386 if (
Op.isUndef()) {
24390 ConcatOps.
append(
Op->op_begin(),
Op->op_end());
24400 EVT VT =
N->getValueType(0);
24401 EVT OpVT =
N->getOperand(0).getValueType();
24417 if (
Op.isUndef()) {
24418 Mask.append((
unsigned)NumOpElts, -1);
24427 int ExtIdx =
Op.getConstantOperandVal(1);
24436 Mask.append((
unsigned)NumOpElts, -1);
24447 if (0 == (NumExtElts % NumElts))
24448 ExtIdx /= (NumExtElts / NumElts);
24449 else if (0 == (NumElts % NumExtElts))
24450 ExtIdx *= (NumElts / NumExtElts);
24455 if (SV0.
isUndef() || SV0 == ExtVec) {
24457 for (
int i = 0; i != NumOpElts; ++i)
24458 Mask.push_back(i + ExtIdx);
24459 }
else if (SV1.
isUndef() || SV1 == ExtVec) {
24461 for (
int i = 0; i != NumOpElts; ++i)
24462 Mask.push_back(i + ExtIdx + NumElts);
24474 unsigned CastOpcode =
N->getOperand(0).getOpcode();
24475 switch (CastOpcode) {
24491 EVT SrcVT =
N->getOperand(0).getOperand(0).getValueType();
24499 if (
Op.getOpcode() != CastOpcode || !
Op.hasOneUse() ||
24500 Op.getOperand(0).getValueType() != SrcVT)
24508 EVT VT =
N->getValueType(0);
24513 switch (CastOpcode) {
24533 return DAG.
getNode(CastOpcode,
DL, VT, NewConcat);
24541 bool LegalOperations) {
24542 EVT VT =
N->getValueType(0);
24543 EVT OpVT =
N->getOperand(0).getValueType();
24548 if (
N->getNumOperands() != 2)
24553 (LegalOperations &&
24564 if (
auto *CurSVN = dyn_cast<ShuffleVectorSDNode>(
Op);
24565 CurSVN && CurSVN->getOperand(1).
isUndef() &&
N->isOnlyUserOf(CurSVN) &&
24568 return !Op.isUndef() &&
24569 (Op.getNode() == CurSVN || is_contained(CurSVN->ops(), Op));
24592 std::iota(FirstShufOpIdentityMask.
begin(), FirstShufOpIdentityMask.
end(), 0);
24593 std::iota(SecondShufOpIdentityMask.
begin(), SecondShufOpIdentityMask.
end(),
24600 assert(!
Op.isUndef() &&
"Not expecting to concatenate UNDEF.");
24601 if (
Op.getNode() == SVN) {
24622 std::array<SDValue, 2> ShufOps;
24623 for (
auto I :
zip(SVN->
ops(), ShufOps)) {
24625 SDValue &NewShufOp = std::get<1>(
I);
24631 ShufOpParts[0] = ShufOp;
24641 if (
N->getNumOperands() == 1)
24642 return N->getOperand(0);
24645 EVT VT =
N->getValueType(0);
24651 [](
const SDValue &
Op) { return Op.isUndef(); })) {
24653 assert(
In.getValueType().isVector() &&
"Must concat vectors");
24663 !(LegalDAG &&
In.getValueType().isScalableVector())) {
24664 unsigned NumOps =
N->getNumOperands() *
In.getNumOperands();
24666 Ops.resize(NumOps, DAG.
getUNDEF(Ops[0].getValueType()));
24676 EVT SVT =
Scalar.getValueType().getVectorElementType();
24677 if (SVT ==
Scalar.getOperand(0).getValueType())
24682 if (!
Scalar.getValueType().isVector() &&
In.hasOneUse()) {
24701 if (VNTNumElms < 2)
24717 auto IsBuildVectorOrUndef = [](
const SDValue &
Op) {
24728 bool FoundMinVT =
false;
24731 EVT OpSVT =
Op.getOperand(0).getValueType();
24732 MinVT = (!FoundMinVT || OpSVT.
bitsLE(MinVT)) ? OpSVT : MinVT;
24735 assert(FoundMinVT &&
"Concat vector type mismatch");
24739 EVT OpVT =
Op.getValueType();
24748 Opnds.
append(
Op->op_begin(),
Op->op_begin() + NumElts);
24750 for (
unsigned i = 0; i != NumElts; ++i)
24758 "Concat vector type mismatch");
24781 N, DAG, TLI, LegalTypes, LegalOperations))
24791 unsigned PartNumElem =
24792 N->getOperand(0).getValueType().getVectorMinNumElements();
24794 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
24805 if (SingleSource.
getNode()) {
24806 if (
Op.getOperand(0) != SingleSource)
24809 SingleSource =
Op.getOperand(0);
24819 unsigned IdentityIndex = i * PartNumElem;
24820 if (
Op.getConstantOperandAPInt(1) != IdentityIndex)
24825 return SingleSource;
24834 V.getOperand(1).getValueType() == SubVT && V.getOperand(2) == Index) {
24835 return V.getOperand(1);
24837 auto *IndexC = dyn_cast<ConstantSDNode>(Index);
24839 V.getOperand(0).getValueType() == SubVT &&
24842 return V.getOperand(SubIdx);
24849 bool LegalOperations) {
24852 unsigned BinOpcode = BinOp.
getOpcode();
24858 if (VecVT != Bop0.
getValueType() || VecVT != Bop1.getValueType())
24872 if (!Sub0 || !Sub1)
24878 return DAG.
getNode(BinOpcode,
SDLoc(Extract), SubVT, Sub0, Sub1,
24885 bool LegalOperations) {
24893 auto *ExtractIndexC = dyn_cast<ConstantSDNode>(Extract->
getOperand(1));
24894 if (!ExtractIndexC)
24910 if (
C &&
C->getValueAPF().isNegZero())
24923 unsigned ExtractIndex = ExtractIndexC->getZExtValue();
24925 "Extract index is not a multiple of the vector length.");
24930 if (WideWidth % NarrowWidth != 0)
24935 unsigned NarrowingRatio = WideWidth / NarrowWidth;
24937 if (WideNumElts % NarrowingRatio != 0)
24942 WideNumElts / NarrowingRatio);
24969 if (NarrowingRatio != 2)
24984 return V.getOperand(ConcatOpNum);
24990 if (SubVecL || SubVecR) {
25021 auto *Ld = dyn_cast<LoadSDNode>(Extract->
getOperand(0));
25041 assert(Index % NumElts == 0 &&
"The extract subvector index is not a "
25042 "multiple of the result's element count");
25061 if (
Offset.isScalable()) {
25084 bool LegalOperations) {
25086 "Must only be called on EXTRACT_SUBVECTOR's");
25091 EVT NarrowVT =
N->getValueType(0);
25097 auto *WideShuffleVector = dyn_cast<ShuffleVectorSDNode>(N0);
25098 if (!WideShuffleVector)
25102 if (!WideShuffleVector->hasOneUse())
25106 if (LegalOperations &&
25110 uint64_t FirstExtractedEltIdx =
N->getConstantOperandVal(1);
25112 assert((FirstExtractedEltIdx % NumEltsExtracted) == 0 &&
25113 "Extract index is not a multiple of the output vector length.");
25118 NewMask.
reserve(NumEltsExtracted);
25120 DemandedSubvectors;
25123 for (
int M : WideShuffleVector->getMask().slice(FirstExtractedEltIdx,
25124 NumEltsExtracted)) {
25125 assert((M >= -1) && (M < (2 * WideNumElts)) &&
25126 "Out-of-bounds shuffle mask?");
25135 int WideShufOpIdx = M / WideNumElts;
25137 int OpEltIdx = M % WideNumElts;
25139 assert((OpEltIdx + WideShufOpIdx * WideNumElts) == M &&
25140 "Shuffle mask vector decomposition failure.");
25143 int OpSubvecIdx = OpEltIdx / NumEltsExtracted;
25145 int OpEltIdxInSubvec = OpEltIdx % NumEltsExtracted;
25147 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted) == OpEltIdx &&
25148 "Shuffle mask subvector decomposition failure.");
25150 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted +
25151 WideShufOpIdx * WideNumElts) == M &&
25152 "Shuffle mask full decomposition failure.");
25154 SDValue Op = WideShuffleVector->getOperand(WideShufOpIdx);
25156 if (
Op.isUndef()) {
25162 const std::pair<SDValue, int> DemandedSubvector =
25163 std::make_pair(
Op, OpSubvecIdx);
25165 if (DemandedSubvectors.insert(DemandedSubvector)) {
25166 if (DemandedSubvectors.size() > 2)
25169 int Index = NumEltsExtracted * OpSubvecIdx;
25177 getFirstIndexOf(DemandedSubvectors.getArrayRef(), DemandedSubvector);
25178 assert((NewOpIdx == 0 || NewOpIdx == 1) &&
"Unexpected operand index.");
25180 int AdjM = OpEltIdxInSubvec + NewOpIdx * NumEltsExtracted;
25183 assert(NewMask.
size() == (
unsigned)NumEltsExtracted &&
"Produced bad mask.");
25184 assert(DemandedSubvectors.size() <= 2 &&
25185 "Should have ended up demanding at most two subvectors.");
25188 if (DemandedSubvectors.empty())
25194 any_of(NewMask, [](
int M) {
return M < 0; }))
25195 for (
auto &DemandedSubvector : DemandedSubvectors)
25196 if (DemandedSubvector.second != 0)
25210 for (
const std::pair<SDValue /*Op*/, int /*SubvectorIndex*/>
25211 &DemandedSubvector : DemandedSubvectors) {
25213 int Index = NumEltsExtracted * DemandedSubvector.second;
25216 DemandedSubvector.first, IndexC));
25219 "Should end up with either one or two ops");
25222 if (NewOps.
size() == 1)
25229 EVT NVT =
N->getValueType(0);
25231 uint64_t ExtIdx =
N->getConstantOperandVal(1);
25246 V.getConstantOperandVal(1)) &&
25266 unsigned InsIdx =
V.getConstantOperandVal(2);
25268 if (InsIdx <= ExtIdx && (ExtIdx + NumSubElts) <= (InsIdx + NumInsElts) &&
25271 V.getValueType().isFixedLengthVector())
25279 V.getOperand(0).getValueType().isVector() &&
25284 unsigned DestNumElts =
V.getValueType().getVectorMinNumElements();
25285 if ((SrcNumElts % DestNumElts) == 0) {
25286 unsigned SrcDestRatio = SrcNumElts / DestNumElts;
25293 V.getOperand(0), NewIndex);
25297 if ((DestNumElts % SrcNumElts) == 0) {
25298 unsigned DestSrcRatio = DestNumElts / SrcNumElts;
25303 if ((ExtIdx % DestSrcRatio) == 0) {
25304 unsigned IndexValScaled = ExtIdx / DestSrcRatio;
25311 V.getOperand(0), NewIndex);
25319 V.getOperand(0), NewIndex);
25329 EVT ConcatSrcVT =
V.getOperand(0).getValueType();
25331 "Concat and extract subvector do not change element type");
25332 assert((ExtIdx % ExtNumElts) == 0 &&
25333 "Extract index is not a multiple of the input vector length.");
25336 unsigned ConcatOpIdx = ExtIdx / ConcatSrcNumElts;
25342 return V.getOperand(ConcatOpIdx);
25350 ConcatSrcNumElts % ExtNumElts == 0) {
25351 unsigned NewExtIdx = ExtIdx - ConcatOpIdx * ConcatSrcNumElts;
25352 assert(NewExtIdx + ExtNumElts <= ConcatSrcNumElts &&
25353 "Trying to extract from >1 concat operand?");
25354 assert(NewExtIdx % ExtNumElts == 0 &&
25355 "Extract index is not a multiple of the input vector length.");
25358 V.getOperand(ConcatOpIdx), NewIndexC);
25370 EVT InVT =
V.getValueType();
25374 if (ExtractSize % EltSize == 0) {
25375 unsigned NumElems = ExtractSize / EltSize;
25378 NumElems == 1 ? EltVT
25386 if (NumElems == 1) {
25387 SDValue Src =
V->getOperand(IdxVal);
25388 if (EltVT != Src.getValueType())
25404 EVT SmallVT =
V.getOperand(1).getValueType();
25405 if (!NVT.
bitsEq(SmallVT))
25413 uint64_t InsIdx =
V.getConstantOperandVal(2);
25423 DAG.
getBitcast(
N->getOperand(0).getValueType(),
V.getOperand(0)),
25453 unsigned HalfNumElts = NumElts / 2;
25456 for (
unsigned i = 0; i != NumElts; ++i) {
25460 if ((Mask[i] % NumElts) >= HalfNumElts)
25462 int M = Mask[i] < (int)NumElts ? Mask[i] : Mask[i] - (
int)HalfNumElts;
25463 if (i < HalfNumElts)
25466 Mask1[i - HalfNumElts] = M;
25489 EVT VT =
N->getValueType(0);
25500 unsigned NumConcats = NumElts / NumElemsPerConcat;
25502 auto IsUndefMaskElt = [](
int i) {
return i == -1; };
25507 if (NumElemsPerConcat * 2 == NumElts && N1.
isUndef() &&
25508 llvm::all_of(Mask.slice(NumElemsPerConcat, NumElemsPerConcat),
25512 Mask.slice(0, NumElemsPerConcat));
25519 for (
unsigned I = 0;
I != NumConcats; ++
I) {
25520 unsigned Begin =
I * NumElemsPerConcat;
25521 ArrayRef<int> SubMask = Mask.slice(Begin, NumElemsPerConcat);
25530 for (
int i = 0; i != (int)NumElemsPerConcat; ++i) {
25531 if (IsUndefMaskElt(SubMask[i]))
25533 if ((SubMask[i] % (
int)NumElemsPerConcat) != i)
25535 int EltOpIdx = SubMask[i] / NumElemsPerConcat;
25536 if (0 <= OpIdx && EltOpIdx != OpIdx)
25540 assert(0 <= OpIdx &&
"Unknown concat_vectors op");
25594 bool IsSplat =
false;
25595 auto *BV0 = dyn_cast<BuildVectorSDNode>(N0);
25596 auto *BV1 = dyn_cast<BuildVectorSDNode>(N1);
25598 if (
SDValue Splat0 = BV0->getSplatValue())
25599 IsSplat = (Splat0 == BV1->getSplatValue());
25603 for (
int M : SVN->
getMask()) {
25606 int Idx = M < (int)NumElts ? M : M - NumElts;
25607 SDValue &S = (M < (int)NumElts ? N0 : N1);
25609 Op = S.getOperand(
Idx);
25624 if (!IsSplat && !DuplicateOps.
insert(
Op).second)
25635 SVT = (SVT.
bitsLT(
Op.getValueType()) ?
Op.getValueType() : SVT);
25651 unsigned Opcode,
EVT VT, std::function<
bool(
unsigned)>
Match,
25653 bool LegalOperations) {
25658 return std::nullopt;
25666 for (
unsigned Scale = 2; Scale < NumElts; Scale *= 2) {
25668 if (NumElts % Scale != 0)
25682 return std::nullopt;
25691 bool LegalOperations) {
25701 Mask = SVN->
getMask()](
unsigned Scale) {
25702 for (
unsigned i = 0; i != NumElts; ++i) {
25705 if ((i % Scale) == 0 && Mask[i] == (int)(i / Scale))
25717 Opcode, VT, isAnyExtend, DAG, TLI,
true, LegalOperations);
25729 bool LegalOperations) {
25730 bool LegalTypes =
true;
25742 auto ForEachDecomposedIndice = [NumElts, &Mask](
auto Fn) {
25743 for (
int &Indice : Mask) {
25746 int OpIdx = (
unsigned)Indice < NumElts ? 0 : 1;
25747 int OpEltIdx = (
unsigned)Indice < NumElts ? Indice : Indice - NumElts;
25748 Fn(Indice, OpIdx, OpEltIdx);
25753 std::array<APInt, 2> OpsDemandedElts;
25754 for (
APInt &OpDemandedElts : OpsDemandedElts)
25756 ForEachDecomposedIndice(
25757 [&OpsDemandedElts](
int &Indice,
int OpIdx,
int OpEltIdx) {
25758 OpsDemandedElts[OpIdx].setBit(OpEltIdx);
25762 std::array<APInt, 2> OpsKnownZeroElts;
25763 for (
auto I :
zip(SVN->
ops(), OpsDemandedElts, OpsKnownZeroElts))
25771 bool HadZeroableElts =
false;
25772 ForEachDecomposedIndice([&OpsKnownZeroElts, &HadZeroableElts](
25773 int &Indice,
int OpIdx,
int OpEltIdx) {
25774 if (OpsKnownZeroElts[OpIdx][OpEltIdx]) {
25776 HadZeroableElts =
true;
25784 if (!HadZeroableElts)
25792 Mask.size() % ScaledMask.
size() == 0 &&
"Unexpected mask widening.");
25793 int Prescale = Mask.size() / ScaledMask.
size();
25795 NumElts = ScaledMask.
size();
25796 EltSizeInBits *= Prescale;
25808 auto isZeroExtend = [NumElts, &ScaledMask](
unsigned Scale) {
25809 assert(Scale >= 2 && Scale <= NumElts && NumElts % Scale == 0 &&
25810 "Unexpected mask scaling factor.");
25812 for (
unsigned SrcElt = 0, NumSrcElts = NumElts / Scale;
25813 SrcElt != NumSrcElts; ++SrcElt) {
25816 assert(MaskChunk.
size() == Scale &&
"Unexpected mask size.");
25817 Mask = Mask.drop_front(MaskChunk.
size());
25820 if (
int FirstIndice = MaskChunk[0]; (
unsigned)FirstIndice != SrcElt)
25825 [](
int Indice) { return Indice == -2; }))
25828 assert(Mask.empty() &&
"Did not process the whole mask?");
25833 for (
bool Commuted : {
false,
true}) {
25838 Opcode, PrescaledVT, isZeroExtend, DAG, TLI, LegalTypes,
25874 if (ExtDstSizeInBits % ExtSrcSizeInBits != 0)
25876 unsigned ExtScale = ExtDstSizeInBits / ExtSrcSizeInBits;
25881 auto isTruncate = [&Mask, &NumElts](
unsigned Scale) {
25882 for (
unsigned i = 0; i != NumElts; ++i) {
25885 if ((i * Scale) < NumElts && Mask[i] == (int)(i * Scale))
25895 if (EltSizeInBits != ExtSrcSizeInBits)
25900 if (isTruncate(ExtScale))
25923 APInt DemandedElts(NumElts, 0);
25927 assert((
unsigned)
Idx < NumElts &&
"Out-of-bounds shuffle indice?");
25930 assert(DemandedElts.
popcount() > 1 &&
"Is a splat shuffle already?");
25935 std::optional<unsigned> MinNonUndefIdx;
25937 if (
Idx < 0 || UndefElts[
Idx])
25939 MinNonUndefIdx = std::min<unsigned>(
Idx, MinNonUndefIdx.value_or(~0U));
25941 if (!MinNonUndefIdx)
25943 assert(*MinNonUndefIdx < NumElts &&
"Expected valid element index.");
25945 for (
int &
Idx : SplatMask) {
25950 Idx = UndefElts[
Idx] ? -1 : *MinNonUndefIdx;
25952 assert(SplatMask != Shuf->
getMask() &&
"Expected mask to change!");
25970 assert(ShufMask.
size() == SplatMask.
size() &&
"Mask length mismatch");
25988 auto CanSimplifyToExistingSplat = [](
ArrayRef<int> UserMask,
25990 for (
unsigned i = 0, e = UserMask.
size(); i != e; ++i)
25991 if (UserMask[i] != -1 && SplatMask[i] == -1 &&
25992 SplatMask[UserMask[i]] != -1)
25996 if (CanSimplifyToExistingSplat(ShufMask, SplatMask))
26002 for (
int Idx : ShufMask)
26015 bool LegalOperations) {
26032 if (VTLanes <= InLanes || VTLanes % InLanes != 0 ||
26033 (LegalOperations &&
26036 int Factor = VTLanes / InLanes;
26063 auto *InnerShuf = dyn_cast<ShuffleVectorSDNode>(OuterShuf->
getOperand(0));
26064 if (!InnerShuf || !InnerShuf->getOperand(1).isUndef())
26069 unsigned NumElts = OuterMask.
size();
26070 assert(NumElts == InnerMask.
size() &&
"Mask length mismatch");
26072 int SplatIndex = -1;
26073 for (
unsigned i = 0; i != NumElts; ++i) {
26075 int OuterMaskElt = OuterMask[i];
26076 if (OuterMaskElt == -1)
26080 int InnerMaskElt = InnerMask[OuterMaskElt];
26081 if (InnerMaskElt == -1)
26085 if (SplatIndex == -1)
26086 SplatIndex = InnerMaskElt;
26089 if (SplatIndex != InnerMaskElt)
26092 CombinedMask[i] = InnerMaskElt;
26094 assert((
all_of(CombinedMask, [](
int M) {
return M == -1; }) ||
26096 "Expected a splat mask");
26100 assert(VT == InnerShuf->getValueType(0) &&
"Expected matching shuffle types");
26105 InnerShuf->getOperand(1), CombinedMask);
26113 int MaskSize = Mask.size();
26114 int EltFromOp0 = -1;
26119 for (
int i = 0; i != MaskSize; ++i) {
26120 if (Mask[i] >= 0 && Mask[i] < MaskSize) {
26122 if (EltFromOp0 != -1)
26125 }
else if (Mask[i] != i + MaskSize) {
26145 if (ShufOp0Index == -1) {
26149 if (ShufOp0Index == -1)
26153 Mask = CommutedMask;
26161 assert(Mask[ShufOp0Index] >= 0 && Mask[ShufOp0Index] < (
int)Mask.size() &&
26162 "Shuffle mask value must be from operand 0");
26180 Op1, Elt, NewInsIndex);
26192 auto *Shuf0 = dyn_cast<ShuffleVectorSDNode>(Shuf->
getOperand(0));
26198 for (
int i = 0, e = (
int)Mask.size(); i != e; ++i) {
26202 assert(Mask[i] >= 0 && Mask[i] < e &&
"Unexpected shuffle mask value");
26206 if (Mask0[Mask[i]] != Mask0[i])
26215 EVT VT =
N->getValueType(0);
26240 bool Changed =
false;
26242 for (
unsigned i = 0; i != NumElts; ++i) {
26244 if (
Idx >= (
int)NumElts) {
26293 if (
auto *
Idx = dyn_cast<ConstantSDNode>(N0.
getOperand(2)))
26294 if (
Idx->getAPIntValue() == SplatIndex)
26320 SDValue ConvInput =
V->getOperand(0);
26327 assert(
V->getNumOperands() == NumElts &&
26328 "BUILD_VECTOR has wrong number of operands");
26330 bool AllSame =
true;
26331 for (
unsigned i = 0; i != NumElts; ++i) {
26332 if (!
V->getOperand(i).isUndef()) {
26333 Base =
V->getOperand(i);
26338 if (!
Base.getNode())
26340 for (
unsigned i = 0; i != NumElts; ++i) {
26341 if (
V->getOperand(i) !=
Base) {
26351 SDValue Splatted =
V->getOperand(SplatIndex);
26357 if (
V->getValueType(0) != VT)
26396 int HalfNumElts = (int)NumElts / 2;
26398 for (
unsigned i = 0; i != NumElts; ++i) {
26400 if (
Idx >= HalfNumElts) {
26401 assert(
Idx < (
int)NumElts &&
"Shuffle mask chooses undef op");
26402 Idx -= HalfNumElts;
26423 EVT SubVT =
RHS.getOperand(0).getValueType();
26424 int NumSubVecs =
RHS.getNumOperands();
26426 assert((NumElts % NumSubElts) == 0 &&
"Subvector mismatch");
26431 if (
all_of(Mask, [NumElts](
int M) {
return M < (int)NumElts; }))
26437 for (
int SubVec = 0; SubVec != NumSubVecs; ++SubVec) {
26438 for (
int SubIdx = 0; SubIdx != (int)NumElts; SubIdx += NumSubElts) {
26440 std::iota(InsertionMask.begin(), InsertionMask.end(), 0);
26443 std::iota(InsertionMask.begin() + SubIdx,
26444 InsertionMask.begin() + SubIdx + NumSubElts,
26445 NumElts + (SubVec * NumSubElts));
26448 bool MatchingShuffle =
true;
26449 for (
int i = 0; i != (int)NumElts; ++i) {
26450 int ExpectIdx = InsertionMask[i];
26451 int ActualIdx =
Mask[i];
26452 if (0 <= ActualIdx && ExpectIdx != ActualIdx) {
26453 MatchingShuffle =
false;
26458 if (MatchingShuffle)
26460 RHS.getOperand(SubVec),
26468 if (
SDValue InsertN1 = ShuffleToInsert(N0, N1, Mask))
26473 if (
SDValue InsertN0 = ShuffleToInsert(N1, N0, CommuteMask))
26481 bool IsInLaneMask =
true;
26486 for (
int I = 0;
I != (int)NumElts; ++
I) {
26490 ClearMask[
I] =
M ==
I ?
I : (
I + NumElts);
26491 IsInLaneMask &= (
M ==
I) || (M == (
int)(
I + NumElts));
26493 APInt &Demanded =
M < (int)NumElts ? DemandedLHS : DemandedRHS;
26494 Demanded.
setBit(M % NumElts);
26498 if (!IsInLaneMask && (!DemandedLHS.
isZero() || !DemandedRHS.
isZero()) &&
26513 for (
int I = 0;
I != (int)NumElts; ++
I)
26515 AndMask[
I] =
Mask[
I] ==
I ? AllOnesElt : ZeroElt;
26552 EVT ScaleVT = SVT.
bitsLT(InnerSVT) ? VT : InnerVT;
26570 for (
int M : OuterMask)
26571 NewMask.
push_back(M < 0 ? -1 : InnerMask[M]);
26602 auto MergeInnerShuffle =
26609 if (OtherSVN->isSplat())
26615 for (
unsigned i = 0; i != NumElts; ++i) {
26616 int Idx = SVN->getMaskElt(i);
26624 Idx = (
Idx < (int)NumElts) ? (
Idx + NumElts) : (
Idx - NumElts);
26627 if (
Idx < (
int)NumElts) {
26630 Idx = OtherSVN->getMaskElt(
Idx);
26636 CurrentVec = (
Idx < (int)NumElts) ? OtherSVN->
getOperand(0)
26645 Mask.push_back(-1);
26652 if (!SV0.getNode() || SV0 == CurrentVec) {
26659 if (!SV1.getNode() || SV1 == CurrentVec) {
26663 Mask.push_back(
Idx + NumElts);
26669 if (
auto *CurrentSVN = dyn_cast<ShuffleVectorSDNode>(CurrentVec)) {
26670 int InnerIdx = CurrentSVN->getMaskElt(
Idx);
26671 if (InnerIdx < 0) {
26672 Mask.push_back(-1);
26675 SDValue InnerVec = (InnerIdx < (int)NumElts)
26679 Mask.push_back(-1);
26682 InnerIdx %= NumElts;
26683 if (InnerVec == SV0) {
26684 Mask.push_back(InnerIdx);
26687 if (InnerVec == SV1) {
26688 Mask.push_back(InnerIdx + NumElts);
26707 if (TLI.isShuffleMaskLegal(Mask, VT))
26712 return TLI.isShuffleMaskLegal(Mask, VT);
26724 assert(N1->getOperand(0).getValueType() == VT &&
26725 "Shuffle types don't match");
26729 bool HasSameOp0 = N0 == SV0;
26730 bool IsSV1Undef = SV1.
isUndef();
26731 if (HasSameOp0 || IsSV1Undef || N0 == SV1)
26740 cast<ShuffleVectorSDNode>(N0)->isSplat() &&
26741 !cast<ShuffleVectorSDNode>(N1)->isSplat()) {
26752 for (
int i = 0; i != 2; ++i) {
26754 N->isOnlyUserOf(
N->getOperand(i).getNode())) {
26757 auto *OtherSV = cast<ShuffleVectorSDNode>(
N->getOperand(i));
26758 assert(OtherSV->getOperand(0).getValueType() == VT &&
26759 "Shuffle types don't match");
26763 if (MergeInnerShuffle(i != 0, SVN, OtherSV,
N->getOperand(1 - i), TLI,
26771 SV1 ? SV1 : DAG.
getUNDEF(VT), Mask);
26781 if (TLI.isBinOp(SrcOpcode) &&
N->isOnlyUserOf(N0.
getNode()) &&
26783 (SrcOpcode == N1.getOpcode() &&
N->isOnlyUserOf(N1.getNode())))) {
26801 SDValue InnerN = Commute ? N1 : N0;
26802 SDValue Op0 = LeftOp ? Op00 : Op01;
26803 SDValue Op1 = LeftOp ? Op10 : Op11;
26808 auto *SVN0 = dyn_cast<ShuffleVectorSDNode>(Op0);
26810 MergeInnerShuffle(Commute, SVN, SVN0, Op1, TLI, SV0, SV1,
26812 (
llvm::any_of(SVN0->getMask(), [](
int M) { return M < 0; }) ||
26818 bool MergedLeft =
false;
26821 if (CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
false) ||
26822 CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
true)) {
26825 LeftMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
26826 LeftSV0 = Op00, LeftSV1 = Op10;
26829 bool MergedRight =
false;
26832 if (CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
false) ||
26833 CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
true)) {
26834 MergedRight =
true;
26836 RightMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
26837 RightSV0 = Op01, RightSV1 = Op11;
26840 if (MergedLeft || MergedRight) {
26843 VT,
DL, LeftSV0 ? LeftSV0 : DAG.
getUNDEF(VT),
26844 LeftSV1 ? LeftSV1 : DAG.
getUNDEF(VT), LeftMask);
26846 VT,
DL, RightSV0 ? RightSV0 : DAG.
getUNDEF(VT),
26847 RightSV1 ? RightSV1 : DAG.
getUNDEF(VT), RightMask);
26848 return DAG.
getNode(SrcOpcode,
DL, VT, LHS, RHS);
26869 EVT VT =
N->getValueType(0);
26879 unsigned Opcode =
Scalar.getOpcode();
26881 if (
Scalar.hasOneUse() &&
Scalar->getNumValues() == 1 &&
26882 TLI.isBinOp(Opcode) &&
Scalar.getValueType() == VecEltVT &&
26883 Scalar.getOperand(0).getValueType() == VecEltVT &&
26884 Scalar.getOperand(1).getValueType() == VecEltVT &&
26885 Scalar->isOnlyUserOf(
Scalar.getOperand(0).getNode()) &&
26886 Scalar->isOnlyUserOf(
Scalar.getOperand(1).getNode()) &&
26891 for (
int i : {0, 1}) {
26895 auto *
C = dyn_cast<ConstantSDNode>(
Scalar.getOperand(i ? 0 : 1));
26902 if (TLI.isShuffleMaskLegal(ShufMask, VT)) {
26917 !
Scalar.getOperand(0).getValueType().isFixedLengthVector())
26921 if (VecEltVT !=
Scalar.getValueType() &&
26927 auto *ExtIndexC = dyn_cast<ConstantSDNode>(
Scalar.getOperand(1));
26935 if (VecEltVT == SrcVT.
getScalarType() && VTNumElts <= SrcNumElts) {
26938 Mask[0] = ExtIndexC->getZExtValue();
26939 SDValue LegalShuffle = TLI.buildLegalVectorShuffle(
26946 return LegalShuffle;
26949 if (VTNumElts != SrcNumElts) {
26962 EVT VT =
N->getValueType(0);
26966 uint64_t InsIdx =
N->getConstantOperandVal(2);
27066 if ((N0.
isUndef() || N0SrcSVT == N1SrcSVT) &&
27078 }
else if ((N1SrcSVT.
getSizeInBits() % EltSizeInBits) == 0) {
27101 if (InsIdx < OtherIdx) {
27105 AddToWorklist(NewOp.
getNode());
27119 Ops[InsIdx / Factor] = N1;
27141 auto Op =
N->getOpcode();
27143 "opcode should be FP16_TO_FP or BF16_TO_FP.");
27159 N->getValueType(0), {N0});
27175 return visitFP16_TO_FP(
N);
27181 unsigned Opcode =
N->getOpcode();
27199 if (!TLI.isOperationLegalOrCustom(Opcode, VT) &&
27200 TLI.isOperationLegalOrCustom(NewOpcode, VT) &&
27202 return DAG.
getNode(NewOpcode,
SDLoc(
N),
N->getValueType(0), N0);
27215 return DAG.
getNode(Opcode,
SDLoc(
N),
N->getValueType(0), Subvec);
27238 if (
SDValue Fused = visitFSUBForFMACombine<VPMatchContext>(
N)) {
27239 AddToWorklist(Fused.getNode());
27247 if (
N->getOpcode() == ISD::VP_GATHER)
27248 if (
SDValue SD = visitVPGATHER(
N))
27251 if (
N->getOpcode() == ISD::VP_SCATTER)
27252 if (
SDValue SD = visitVPSCATTER(
N))
27255 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_LOAD)
27256 if (
SDValue SD = visitVP_STRIDED_LOAD(
N))
27259 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_STORE)
27260 if (
SDValue SD = visitVP_STRIDED_STORE(
N))
27266 bool AreAllEltsDisabled =
false;
27270 AreAllEltsDisabled |=
27274 if (!AreAllEltsDisabled) {
27275 switch (
N->getOpcode()) {
27277 return visitVP_FADD(
N);
27279 return visitVP_FSUB(
N);
27281 return visitFMA<VPMatchContext>(
N);
27282 case ISD::VP_SELECT:
27283 return visitVP_SELECT(
N);
27285 return visitMUL<VPMatchContext>(
N);
27287 return foldSubCtlzNot<VPMatchContext>(
N, DAG);
27296 return DAG.
getUNDEF(
N->getValueType(0));
27300 if (
const auto *MemSD = dyn_cast<MemSDNode>(
N)) {
27301 if (MemSD->writeMem())
27302 return MemSD->getChain();
27303 return CombineTo(
N, DAG.
getUNDEF(
N->getValueType(0)), MemSD->getChain());
27308 return N->getOperand(0);
27316 EVT MemVT = cast<FPStateAccessSDNode>(
N)->getMemoryVT();
27321 for (
auto *U :
Ptr->users()) {
27324 if (
auto *Ld = dyn_cast<LoadSDNode>(U)) {
27325 if (LdNode && LdNode != Ld)
27340 if (
U.getResNo() == 0) {
27341 if (
auto *St = dyn_cast<StoreSDNode>(
U.getUser())) {
27359 CombineTo(StNode, Res,
false);
27366 EVT MemVT = cast<FPStateAccessSDNode>(
N)->getMemoryVT();
27370 for (
auto *U :
Ptr->users()) {
27373 if (
auto *St = dyn_cast<StoreSDNode>(U)) {
27374 if (StNode && StNode != St)
27389 auto *LdNode = dyn_cast<LoadSDNode>(StValue);
27410 EVT VT =
N->getValueType(0);
27417 if (LegalOperations)
27423 EVT RVT =
RHS.getValueType();
27424 unsigned NumElts =
RHS.getNumOperands();
27429 auto BuildClearMask = [&](
int Split) {
27430 int NumSubElts = NumElts *
Split;
27434 for (
int i = 0; i != NumSubElts; ++i) {
27435 int EltIdx = i /
Split;
27436 int SubIdx = i %
Split;
27446 if (
auto *Cst = dyn_cast<ConstantSDNode>(Elt))
27447 Bits = Cst->getAPIntValue();
27448 else if (
auto *CstFP = dyn_cast<ConstantFPSDNode>(Elt))
27455 Bits =
Bits.extractBits(NumSubBits, (Split - SubIdx - 1) * NumSubBits);
27457 Bits =
Bits.extractBits(NumSubBits, SubIdx * NumSubBits);
27459 if (
Bits.isAllOnes())
27461 else if (Bits == 0)
27470 if (!TLI.isVectorClearMaskLegal(Indices, ClearVT))
27484 for (
int Split = 1;
Split <= MaxSplit; ++
Split)
27486 if (
SDValue S = BuildClearMask(Split))
27495 const SDLoc &
DL,
bool LegalTypes) {
27498 unsigned Opcode =
N->getOpcode();
27499 EVT VT =
N->getValueType(0);
27506 int Index0, Index1;
27513 if (!Src0 || !Src1 || Index0 != Index1 ||
27542 Ops[Index0] = ScalarBO;
27552 EVT VT =
N->getValueType(0);
27553 assert(VT.
isVector() &&
"SimplifyVCastOp only works on vectors!");
27555 unsigned Opcode =
N->getOpcode();
27585 EVT VT =
N->getValueType(0);
27586 assert(VT.
isVector() &&
"SimplifyVBinOp only works on vectors!");
27590 unsigned Opcode =
N->getOpcode();
27601 auto *Shuf0 = dyn_cast<ShuffleVectorSDNode>(LHS);
27602 auto *Shuf1 = dyn_cast<ShuffleVectorSDNode>(RHS);
27603 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
27604 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
27607 RHS.getOperand(0), Flags);
27619 Shuf0->hasOneUse() && Shuf0->getOperand(1).isUndef() &&
27628 Shuf1->hasOneUse() && Shuf1->getOperand(1).isUndef() &&
27644 LHS.getOperand(2) ==
RHS.getOperand(2) &&
27649 EVT NarrowVT =
X.getValueType();
27650 if (NarrowVT ==
Y.getValueType() &&
27652 LegalOperations)) {
27665 return Op.isUndef() ||
27666 ISD::isBuildVectorOfConstantSDNodes(Op.getNode());
27675 if (ConcatWithConstantOrUndef(LHS) && ConcatWithConstantOrUndef(RHS) &&
27677 EVT NarrowVT =
LHS.getOperand(0).getValueType();
27678 if (NarrowVT ==
RHS.getOperand(0).getValueType() &&
27680 unsigned NumOperands =
LHS.getNumOperands();
27682 for (
unsigned i = 0; i != NumOperands; ++i) {
27685 RHS.getOperand(i)));
27701 "First argument must be a SetCC node!");
27704 cast<CondCodeSDNode>(N0.
getOperand(2))->get());
27709 if (
SCC.getNode()) {
27716 SCC.getOperand(0),
SCC.getOperand(1),
27717 SCC.getOperand(4), Flags);
27718 AddToWorklist(
SETCC.getNode());
27720 SCC.getOperand(2),
SCC.getOperand(3));
27735bool DAGCombiner::SimplifySelectOps(
SDNode *TheSelect,
SDValue LHS,
27748 CC = cast<CondCodeSDNode>(TheSelect->
getOperand(4))->get();
27755 CC = cast<CondCodeSDNode>(
Cmp.getOperand(2))->get();
27756 CmpLHS =
Cmp.getOperand(0);
27760 if (Zero &&
Zero->isZero() &&
27764 CombineTo(TheSelect, Sqrt);
27774 if (
LHS.getOpcode() !=
RHS.getOpcode() ||
27787 if (
LHS.getOperand(0) !=
RHS.getOperand(0) ||
27831 Visited.
insert(TheSelect);
27910 CombineTo(TheSelect, Load);
27914 CombineTo(
LHS.getNode(),
Load.getValue(0),
Load.getValue(1));
27915 CombineTo(
RHS.getNode(),
Load.getValue(0),
Load.getValue(1));
27955 auto *N2C = dyn_cast<ConstantSDNode>(N2.
getNode());
27956 if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue() - 1)) == 0)) {
27957 unsigned ShCt = XType.
getSizeInBits() - N2C->getAPIntValue().logBase2() - 1;
27961 AddToWorklist(Shift.
getNode());
27963 if (XType.
bitsGT(AType)) {
27965 AddToWorklist(Shift.
getNode());
27969 Shift = DAG.
getNOT(
DL, Shift, AType);
27981 AddToWorklist(Shift.
getNode());
27983 if (XType.
bitsGT(AType)) {
27985 AddToWorklist(Shift.
getNode());
27989 Shift = DAG.
getNOT(
DL, Shift, AType);
28052 EVT VT =
N->getValueType(0);
28060 EVT IntVT =
Int.getValueType();
28074 SignMask = ~SignMask;
28080 SignMask = ~SignMask;
28085 AddToWorklist(
Int.getNode());
28093SDValue DAGCombiner::convertSelectOfFPConstantsToLoadOffset(
28101 auto *TV = dyn_cast<ConstantFPSDNode>(N2);
28102 auto *FV = dyn_cast<ConstantFPSDNode>(N3);
28109 TLI.
isFPImmLegal(TV->getValueAPF(), TV->getValueType(0), ForCodeSize) ||
28110 TLI.
isFPImmLegal(FV->getValueAPF(), FV->getValueType(0), ForCodeSize))
28115 if (!TV->hasOneUse() && !FV->hasOneUse())
28119 const_cast<ConstantFP*
>(TV->getConstantFPValue()) };
28127 Align Alignment = cast<ConstantPoolSDNode>(CPIdx)->getAlign();
28136 AddToWorklist(
Cond.getNode());
28138 AddToWorklist(CstOffset.
getNode());
28140 AddToWorklist(CPIdx.
getNode());
28150 bool NotExtCompare) {
28152 if (N2 == N3)
return N2;
28157 auto *N1C = dyn_cast<ConstantSDNode>(N1.
getNode());
28158 auto *N2C = dyn_cast<ConstantSDNode>(N2.
getNode());
28159 auto *N3C = dyn_cast<ConstantSDNode>(N3.
getNode());
28163 AddToWorklist(
SCC.getNode());
28164 if (
auto *SCCC = dyn_cast<ConstantSDNode>(SCC)) {
28167 return !(SCCC->isZero()) ? N2 : N3;
28172 convertSelectOfFPConstantsToLoadOffset(
DL, N0, N1, N2, N3,
CC))
28175 if (
SDValue V = foldSelectCCToShiftAnd(
DL, N0, N1, N2, N3,
CC))
28187 auto *ConstAndRHS = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
28188 if (ConstAndRHS && ConstAndRHS->getAPIntValue().popcount() == 1) {
28190 const APInt &AndMask = ConstAndRHS->getAPIntValue();
28208 bool Fold = N2C &&
isNullConstant(N3) && N2C->getAPIntValue().isPowerOf2();
28209 bool Swap = N3C &&
isNullConstant(N2) && N3C->getAPIntValue().isPowerOf2();
28211 if ((Fold || Swap) &&
28223 if (NotExtCompare && N2C->isOne())
28236 AddToWorklist(
SCC.getNode());
28237 AddToWorklist(Temp.
getNode());
28242 unsigned ShCt = N2C->getAPIntValue().logBase2();
28267 if (
auto *ValueOnZeroC = dyn_cast<ConstantSDNode>(ValueOnZero)) {
28289 if (!NotExtCompare && N1C && N2C && N3C &&
28290 N2C->getAPIntValue() == ~N3C->getAPIntValue() &&
28305 if (
SDValue ABD = foldSelectToABD(N0, N1, N2, N3,
CC,
DL))
28314 bool foldBooleans) {
28316 DagCombineInfo(DAG, Level,
false,
this);
28414 bool AssumeNonZero) {
28417 auto PeekThroughCastsAndTrunc = [](
SDValue V) {
28419 switch (V.getOpcode()) {
28422 V = V.getOperand(0);
28433 Op = PeekThroughCastsAndTrunc(
Op);
28439 if (
C->isZero() ||
C->isOpaque())
28442 if (
C->getAPIntValue().isPowerOf2()) {
28458 for (
const APInt &Pow2 : Pow2Constants)
28467 auto CastToVT = [&](
EVT NewVT,
SDValue ToCast) {
28468 ToCast = PeekThroughCastsAndTrunc(ToCast);
28469 EVT CurVT = ToCast.getValueType();
28470 if (NewVT == CurVT)
28482 if (AssumeNonZero ||
Op->getFlags().hasNoUnsignedWrap() ||
28485 Depth + 1, AssumeNonZero))
28487 CastToVT(VT,
Op.getOperand(1)));
28494 Depth + 1, AssumeNonZero))
28496 Depth + 1, AssumeNonZero))
28497 return DAG.
getSelect(
DL, VT,
Op.getOperand(0), LogX, LogY);
28512 return DAG.
getNode(
Op.getOpcode(),
DL, VT, LogX, LogY);
28521 bool KnownNonZero,
bool InexpensiveOnly,
28522 std::optional<EVT> OutVT) {
28523 EVT VT = OutVT ? *OutVT :
V.getValueType();
28524 SDValue InexpensiveLogBase2 =
28527 return InexpensiveLogBase2;
28549 EVT VT =
Op.getValueType();
28557 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
28564 AddToWorklist(Est.getNode());
28572 for (
int i = 0; i < Iterations; ++i) {
28575 if (i == Iterations - 1) {
28577 AddToWorklist(MulEst.
getNode());
28581 AddToWorklist(NewEst.
getNode());
28584 (i == Iterations - 1 ?
N : FPOne), NewEst, Flags);
28585 AddToWorklist(NewEst.
getNode());
28588 AddToWorklist(NewEst.
getNode());
28591 AddToWorklist(Est.getNode());
28596 AddToWorklist(Est.getNode());
28612 unsigned Iterations,
28624 for (
unsigned i = 0; i < Iterations; ++i) {
28644 unsigned Iterations,
28657 for (
unsigned i = 0; i < Iterations; ++i) {
28666 if (Reciprocal || (i + 1) < Iterations) {
28689 EVT VT =
Op.getValueType();
28697 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
28704 bool UseOneConstNR =
false;
28708 AddToWorklist(Est.
getNode());
28710 if (Iterations > 0)
28711 Est = UseOneConstNR
28712 ? buildSqrtNROneConst(
Op, Est, Iterations, Flags, Reciprocal)
28713 : buildSqrtNRTwoConst(
Op, Est, Iterations,
Flags, Reciprocal);
28733 return buildSqrtEstimateImpl(
Op, Flags,
true);
28737 return buildSqrtEstimateImpl(
Op, Flags,
false);
28741bool DAGCombiner::mayAlias(
SDNode *Op0,
SDNode *Op1)
const {
28743 struct MemUseCharacteristics {
28752 auto getCharacteristics = [](
SDNode *
N) -> MemUseCharacteristics {
28753 if (
const auto *LSN = dyn_cast<LSBaseSDNode>(
N)) {
28755 if (
auto *
C = dyn_cast<ConstantSDNode>(LSN->getOffset()))
28758 ? -1 *
C->getSExtValue()
28761 return {LSN->isVolatile(), LSN->isAtomic(),
28762 LSN->getBasePtr(),
Offset ,
28765 if (
const auto *LN = cast<LifetimeSDNode>(
N))
28769 (LN->hasOffset()) ? LN->getOffset() : 0,
28782 MemUseCharacteristics MUC0 = getCharacteristics(Op0),
28783 MUC1 = getCharacteristics(Op1);
28786 if (MUC0.BasePtr.getNode() && MUC0.BasePtr == MUC1.BasePtr &&
28787 MUC0.Offset == MUC1.Offset)
28791 if (MUC0.IsVolatile && MUC1.IsVolatile)
28796 if (MUC0.IsAtomic && MUC1.IsAtomic)
28799 if (MUC0.MMO && MUC1.MMO) {
28800 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
28801 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
28807 if ((MUC0.NumBytes.hasValue() && MUC0.NumBytes.isScalable() &&
28808 MUC0.Offset != 0) ||
28809 (MUC1.NumBytes.hasValue() && MUC1.NumBytes.isScalable() &&
28821 if (!MUC0.MMO || !MUC1.MMO)
28827 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
28828 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
28836 int64_t SrcValOffset0 = MUC0.MMO->getOffset();
28837 int64_t SrcValOffset1 = MUC1.MMO->getOffset();
28838 Align OrigAlignment0 = MUC0.MMO->getBaseAlign();
28839 Align OrigAlignment1 = MUC1.MMO->getBaseAlign();
28843 if (OrigAlignment0 == OrigAlignment1 && SrcValOffset0 != SrcValOffset1 &&
28849 int64_t OffAlign0 = SrcValOffset0 % OrigAlignment0.
value();
28850 int64_t OffAlign1 = SrcValOffset1 % OrigAlignment1.
value();
28854 if ((OffAlign0 +
static_cast<int64_t
>(
28856 (OffAlign1 +
static_cast<int64_t
>(
28870 if (
UseAA && AA && MUC0.MMO->getValue() && MUC1.MMO->getValue() &&
28873 (!Size0.
isScalable() || SrcValOffset0 == 0) &&
28874 (!Size1.
isScalable() || SrcValOffset1 == 0)) {
28876 int64_t MinOffset = std::min(SrcValOffset0, SrcValOffset1);
28899void DAGCombiner::GatherAllAliases(
SDNode *
N,
SDValue OriginalChain,
28906 const bool IsLoad = isa<LoadSDNode>(
N) && cast<LoadSDNode>(
N)->isSimple();
28910 unsigned Depth = 0;
28913 auto ImproveChain = [&](
SDValue &
C) ->
bool {
28914 switch (
C.getOpcode()) {
28923 bool IsOpLoad = isa<LoadSDNode>(
C.getNode()) &&
28924 cast<LSBaseSDNode>(
C.getNode())->isSimple();
28925 if ((IsLoad && IsOpLoad) || !
mayAlias(
N,
C.getNode())) {
28927 C =
C.getOperand(0);
28936 C =
C.getOperand(0);
28945 C =
C.getOperand(0);
28958 while (!Chains.
empty()) {
28992 if (ImproveChain(Chain)) {
29014 GatherAllAliases(
N, OldChain, Aliases);
29017 if (Aliases.
empty())
29021 if (Aliases.
size() == 1)
29041bool DAGCombiner::parallelizeChainedStores(
StoreSDNode *St) {
29058 if (!
BasePtr.getBase().getNode())
29062 if (
BasePtr.getBase().isUndef())
29080 if (Chain->getMemoryVT().isScalableVector())
29084 if (!
SDValue(Chain, 0)->hasOneUse())
29087 if (!Chain->isSimple() || Chain->isIndexed())
29096 int64_t
Length = (Chain->getMemoryVT().getSizeInBits() + 7) / 8;
29099 auto I = Intervals.find(
Offset);
29104 if (
I != Intervals.begin() && (--
I).stop() <=
Offset)
29113 if (ChainedStores.
empty())
29120 for (
unsigned I = ChainedStores.
size();
I;) {
29122 SDValue BetterChain = FindBetterChain(S, NewChain);
29126 ChainedStores[
I] = S;
29130 SDValue BetterChain = FindBetterChain(St, NewChain);
29145 auto hasImprovedChain = [&](
SDValue ST) ->
bool {
29146 return ST->getOperand(0) != NewChain;
29148 bool AddNewChain =
llvm::all_of(TFOps, hasImprovedChain);
29158 AddToWorklist(
Op.getNode());
29159 AddToWorklist(STChain);
29163bool DAGCombiner::findBetterNeighborChains(
StoreSDNode *St) {
29170 if (!
BasePtr.getBase().getNode())
29174 if (
BasePtr.getBase().isUndef())
29178 if (parallelizeChainedStores(St))
29183 if (St->
getChain() != BetterChain) {
29184 replaceStoreChain(St, BetterChain);
29194 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)
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)
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)
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...