84#define DEBUG_TYPE "dagcombine"
86STATISTIC(NodesCombined ,
"Number of dag nodes combined");
87STATISTIC(PreIndexedNodes ,
"Number of pre-indexed nodes created");
88STATISTIC(PostIndexedNodes,
"Number of post-indexed nodes created");
89STATISTIC(OpsNarrowed ,
"Number of load/op/store narrowed");
90STATISTIC(LdStFP2Int ,
"Number of fp load/store pairs transformed to int");
92STATISTIC(NumFPLogicOpsConv,
"Number of logic ops converted to fp ops");
95 "Controls whether a DAG combine is performed for a node");
99 cl::desc(
"Enable DAG combiner's use of IR alias analysis"));
103 cl::desc(
"Enable DAG combiner's use of TBAA"));
108 cl::desc(
"Only use DAG-combiner alias analysis in this"
116 cl::desc(
"Bypass the profitability model of load slicing"),
121 cl::desc(
"DAG combiner may split indexing from loads"));
125 cl::desc(
"DAG combiner enable merging multiple stores "
126 "into a wider store"));
130 cl::desc(
"Limit the number of operands to inline for Token Factors"));
134 cl::desc(
"Limit the number of times for the same StoreNode and RootNode "
135 "to bail out in store merging dependence check"));
139 cl::desc(
"DAG combiner enable reducing the width of load/op/store "
142 "combiner-reduce-load-op-store-width-force-narrowing-profitable",
144 cl::desc(
"DAG combiner force override the narrowing profitable check when "
145 "reducing the width of load/op/store sequences"));
149 cl::desc(
"DAG combiner enable load/<replace bytes>/store with "
150 "a narrower store"));
155 "Enable merging extends and rounds into FCOPYSIGN on vector types"));
164 bool LegalDAG =
false;
165 bool LegalOperations =
false;
166 bool LegalTypes =
false;
168 bool DisableGenericCombines;
204 void AddUsersToWorklist(
SDNode *
N) {
210 void AddToWorklistWithUsers(
SDNode *
N) {
211 AddUsersToWorklist(
N);
218 void clearAddedDanglingWorklistEntries() {
220 while (!PruningList.
empty()) {
223 recursivelyDeleteUnusedNodes(
N);
227 SDNode *getNextWorklistEntry() {
229 clearAddedDanglingWorklistEntries();
233 while (!
N && !Worklist.
empty()) {
238 assert(
N->getCombinerWorklistIndex() >= 0 &&
239 "Found a worklist entry without a corresponding map entry!");
241 N->setCombinerWorklistIndex(-2);
251 : DAG(
D), TLI(
D.getTargetLoweringInfo()),
252 STI(
D.getSubtarget().getSelectionDAGInfo()), OptLevel(OL), AA(AA) {
256 MaximumLegalStoreInBits = 0;
262 VT.getSizeInBits().getKnownMinValue() >= MaximumLegalStoreInBits)
263 MaximumLegalStoreInBits = VT.getSizeInBits().getKnownMinValue();
266 void ConsiderForPruning(
SDNode *
N) {
273 void AddToWorklist(
SDNode *
N,
bool IsCandidateForPruning =
true,
274 bool SkipIfCombinedBefore =
false) {
276 "Deleted Node added to Worklist");
283 if (SkipIfCombinedBefore &&
N->getCombinerWorklistIndex() == -2)
286 if (IsCandidateForPruning)
287 ConsiderForPruning(
N);
289 if (
N->getCombinerWorklistIndex() < 0) {
290 N->setCombinerWorklistIndex(Worklist.
size());
296 void removeFromWorklist(
SDNode *
N) {
298 StoreRootCountMap.
erase(
N);
300 int WorklistIndex =
N->getCombinerWorklistIndex();
304 if (WorklistIndex < 0)
308 Worklist[WorklistIndex] =
nullptr;
309 N->setCombinerWorklistIndex(-1);
312 void deleteAndRecombine(
SDNode *
N);
313 bool recursivelyDeleteUnusedNodes(
SDNode *
N);
321 return CombineTo(
N, &Res, 1, AddTo);
328 return CombineTo(
N, To, 2, AddTo);
334 unsigned MaximumLegalStoreInBits;
340 unsigned BitWidth =
Op.getScalarValueSizeInBits();
346 EVT VT =
Op.getValueType();
350 return SimplifyDemandedBits(
Op,
DemandedBits, DemandedElts,
false);
356 bool SimplifyDemandedVectorElts(
SDValue Op) {
358 if (
Op.getValueType().isScalableVector())
361 unsigned NumElts =
Op.getValueType().getVectorNumElements();
363 return SimplifyDemandedVectorElts(
Op, DemandedElts);
367 const APInt &DemandedElts,
368 bool AssumeSingleUse =
false);
369 bool SimplifyDemandedVectorElts(
SDValue Op,
const APInt &DemandedElts,
370 bool AssumeSingleUse =
false);
372 bool CombineToPreIndexedLoadStore(
SDNode *
N);
373 bool CombineToPostIndexedLoadStore(
SDNode *
N);
398 void ReplaceLoadWithPromotedLoad(
SDNode *Load,
SDNode *ExtLoad);
539 bool refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
SDNode *
N);
571 template <
class MatchContextClass>
573 template <
class MatchContextClass>
578 bool reassociationCanBreakAddressingModePattern(
unsigned Opc,
587 SDValue reassociateReduction(
unsigned RedOpc,
unsigned Opc,
const SDLoc &
DL,
601 bool NotExtCompare =
false);
602 SDValue convertSelectOfFPConstantsToLoadOffset(
619 const SDLoc &
DL,
bool foldBooleans);
623 SDValue &
CC,
bool MatchStrict =
false)
const;
624 bool isOneUseSetCC(
SDValue N)
const;
649 bool KnownNeverZero =
false,
650 bool InexpensiveOnly =
false,
651 std::optional<EVT> OutVT = std::nullopt);
661 bool DemandHighBits =
true);
665 unsigned PosOpcode,
unsigned NegOpcode,
669 unsigned PosOpcode,
unsigned NegOpcode,
685 SDValue VecIn2,
unsigned LeftIdx,
720 int64_t OffsetFromBase;
723 : MemNode(
N), OffsetFromBase(
Offset) {}
728 StoreSource getStoreSource(
SDValue StoreVal) {
732 return StoreSource::Constant;
736 return StoreSource::Constant;
737 return StoreSource::Unknown;
740 return StoreSource::Extract;
742 return StoreSource::Load;
744 return StoreSource::Unknown;
752 bool isMulAddWithConstProfitable(
SDNode *MulNode,
SDValue AddNode,
759 EVT LoadResultTy,
EVT &ExtVT);
764 EVT &MemVT,
unsigned ShAmt = 0);
772 bool BackwardsPropagateMask(
SDNode *
N);
789 EVT MemVT,
unsigned NumStores,
790 bool IsConstantSrc,
bool UseVector,
803 bool checkMergeStoreCandidatesForDependencies(
811 int64_t ElementSizeBytes)
const;
816 unsigned NumConsecutiveStores,
817 EVT MemVT,
SDNode *Root,
bool AllowVectors);
824 unsigned NumConsecutiveStores,
EVT MemVT,
830 unsigned NumConsecutiveStores,
EVT MemVT,
831 SDNode *Root,
bool AllowVectors,
832 bool IsNonTemporalStore,
bool IsNonTemporalLoad);
851 bool hasOperation(
unsigned Opcode,
EVT VT) {
862 EVT getShiftAmountTy(
EVT LHSTy) {
868 bool isTypeLegal(
const EVT &VT) {
869 if (!LegalTypes)
return true;
874 EVT getSetCCResultType(
EVT VT)
const {
889 explicit WorklistRemover(DAGCombiner &dc)
890 :
SelectionDAG::DAGUpdateListener(dc.getDAG()), DC(dc) {}
893 DC.removeFromWorklist(
N);
901 explicit WorklistInserter(DAGCombiner &dc)
902 :
SelectionDAG::DAGUpdateListener(dc.getDAG()), DC(dc) {}
916 ((DAGCombiner*)
DC)->AddToWorklist(
N);
921 return ((DAGCombiner*)DC)->CombineTo(
N, &To[0], To.
size(), AddTo);
926 return ((DAGCombiner*)DC)->CombineTo(
N, Res, AddTo);
931 return ((DAGCombiner*)DC)->CombineTo(
N, Res0, Res1, AddTo);
936 return ((DAGCombiner*)DC)->recursivelyDeleteUnusedNodes(
N);
941 return ((DAGCombiner*)DC)->CommitTargetLoweringOpt(TLO);
948void DAGCombiner::deleteAndRecombine(
SDNode *
N) {
949 removeFromWorklist(
N);
957 if (
Op->hasOneUse() ||
Op->getNumValues() > 1)
958 AddToWorklist(
Op.getNode());
967 unsigned Bits =
Offset + std::max(
LHS.getBitWidth(),
RHS.getBitWidth());
980 LHS =
N.getOperand(0);
981 RHS =
N.getOperand(1);
982 CC =
N.getOperand(2);
989 LHS =
N.getOperand(1);
990 RHS =
N.getOperand(2);
991 CC =
N.getOperand(3);
1003 LHS =
N.getOperand(0);
1004 RHS =
N.getOperand(1);
1005 CC =
N.getOperand(4);
1012bool DAGCombiner::isOneUseSetCC(
SDValue N)
const {
1014 if (isSetCCEquivalent(
N, N0, N1, N2) &&
N->hasOneUse())
1026 MaskForTy = 0xFFULL;
1029 MaskForTy = 0xFFFFULL;
1032 MaskForTy = 0xFFFFFFFFULL;
1051 return !(Const->isOpaque() && NoOpaques);
1054 unsigned BitWidth =
N.getScalarValueSizeInBits();
1059 if (!Const || Const->getAPIntValue().getBitWidth() !=
BitWidth ||
1060 (Const->isOpaque() && NoOpaques))
1079 !cast<ConstantSDNode>(LD->getOperand(2))->isOpaque());
1082bool DAGCombiner::reassociationCanBreakAddressingModePattern(
unsigned Opc,
1115 ScalableOffset = -ScalableOffset;
1117 if (
auto *LoadStore = dyn_cast<MemSDNode>(
Node);
1123 unsigned AS =
LoadStore->getAddressSpace();
1136 auto *C2 = dyn_cast<ConstantSDNode>(N1);
1140 const APInt &C2APIntVal = C2->getAPIntValue();
1144 if (
auto *C1 = dyn_cast<ConstantSDNode>(N0.
getOperand(1))) {
1148 const APInt &C1APIntVal = C1->getAPIntValue();
1149 const APInt CombinedValueIntVal = C1APIntVal + C2APIntVal;
1152 const int64_t CombinedValue = CombinedValueIntVal.
getSExtValue();
1155 if (
auto *LoadStore = dyn_cast<MemSDNode>(
Node)) {
1161 AM.
BaseOffs = C2APIntVal.getSExtValue();
1163 unsigned AS =
LoadStore->getAddressSpace();
1175 if (
auto *GA = dyn_cast<GlobalAddressSDNode>(N0.
getOperand(1)))
1188 AM.
BaseOffs = C2APIntVal.getSExtValue();
1190 unsigned AS =
LoadStore->getAddressSpace();
1203SDValue DAGCombiner::reassociateOpsCommutative(
unsigned Opc,
const SDLoc &
DL,
1217 Flags.hasNoUnsignedWrap())
1225 return DAG.
getNode(Opc,
DL, VT, N00, OpNode, NewFlags);
1233 return DAG.
getNode(Opc,
DL, VT, OpNode, N01, NewFlags);
1243 if (N1 == N00 || N1 == N01)
1289 if (CC1 == CC00 && CC1 != CC01) {
1291 return DAG.
getNode(Opc,
DL, VT, OpNode, N01, Flags);
1293 if (CC1 == CC01 && CC1 != CC00) {
1295 return DAG.
getNode(Opc,
DL, VT, OpNode, N00, Flags);
1313 if (!
Flags.hasAllowReassociation() || !
Flags.hasNoSignedZeros())
1316 if (
SDValue Combined = reassociateOpsCommutative(Opc,
DL, N0, N1, Flags))
1318 if (
SDValue Combined = reassociateOpsCommutative(Opc,
DL, N1, N0, Flags))
1326SDValue DAGCombiner::reassociateReduction(
unsigned RedOpc,
unsigned Opc,
1344 assert(
N->getNumValues() == NumTo &&
"Broken CombineTo call!");
1348 dbgs() <<
" and " << NumTo - 1 <<
" other values\n");
1349 for (
unsigned i = 0, e = NumTo; i !=
e; ++i)
1351 N->getValueType(i) == To[i].getValueType()) &&
1352 "Cannot combine value to value of different type!");
1354 WorklistRemover DeadNodes(*
this);
1358 for (
unsigned i = 0, e = NumTo; i !=
e; ++i) {
1360 AddToWorklistWithUsers(To[i].
getNode());
1368 deleteAndRecombine(
N);
1386 recursivelyDeleteUnusedNodes(TLO.
Old.
getNode());
1392 const APInt &DemandedElts,
1393 bool AssumeSingleUse) {
1401 AddToWorklist(
Op.getNode());
1403 CommitTargetLoweringOpt(TLO);
1410bool DAGCombiner::SimplifyDemandedVectorElts(
SDValue Op,
1411 const APInt &DemandedElts,
1412 bool AssumeSingleUse) {
1414 APInt KnownUndef, KnownZero;
1416 TLO, 0, AssumeSingleUse))
1420 AddToWorklist(
Op.getNode());
1422 CommitTargetLoweringOpt(TLO);
1426void DAGCombiner::ReplaceLoadWithPromotedLoad(
SDNode *Load,
SDNode *ExtLoad) {
1428 EVT VT =
Load->getValueType(0);
1437 AddToWorklist(Trunc.
getNode());
1438 recursivelyDeleteUnusedNodes(Load);
1446 EVT MemVT =
LD->getMemoryVT();
1448 :
LD->getExtensionType();
1451 LD->getChain(),
LD->getBasePtr(),
1452 MemVT,
LD->getMemOperand());
1455 unsigned Opc =
Op.getOpcode();
1459 if (
SDValue Op0 = SExtPromoteOperand(
Op.getOperand(0), PVT))
1463 if (
SDValue Op0 = ZExtPromoteOperand(
Op.getOperand(0), PVT))
1481 EVT OldVT =
Op.getValueType();
1483 bool Replace =
false;
1484 SDValue NewOp = PromoteOperand(
Op, PVT, Replace);
1487 AddToWorklist(NewOp.
getNode());
1490 ReplaceLoadWithPromotedLoad(
Op.getNode(), NewOp.
getNode());
1496 EVT OldVT =
Op.getValueType();
1498 bool Replace =
false;
1499 SDValue NewOp = PromoteOperand(
Op, PVT, Replace);
1502 AddToWorklist(NewOp.
getNode());
1505 ReplaceLoadWithPromotedLoad(
Op.getNode(), NewOp.
getNode());
1513 if (!LegalOperations)
1516 EVT VT =
Op.getValueType();
1522 unsigned Opc =
Op.getOpcode();
1530 assert(PVT != VT &&
"Don't know what type to promote to!");
1534 bool Replace0 =
false;
1536 SDValue NN0 = PromoteOperand(N0, PVT, Replace0);
1538 bool Replace1 =
false;
1540 SDValue NN1 = PromoteOperand(N1, PVT, Replace1);
1552 Replace1 &= (N0 != N1) && !N1->
hasOneUse();
1555 CombineTo(
Op.getNode(), RV);
1581 if (!LegalOperations)
1584 EVT VT =
Op.getValueType();
1590 unsigned Opc =
Op.getOpcode();
1598 assert(PVT != VT &&
"Don't know what type to promote to!");
1602 bool Replace =
false;
1605 N0 = SExtPromoteOperand(N0, PVT);
1607 N0 = ZExtPromoteOperand(N0, PVT);
1609 N0 = PromoteOperand(N0, PVT, Replace);
1620 ReplaceLoadWithPromotedLoad(
Op.getOperand(0).getNode(), N0.
getNode());
1630 if (!LegalOperations)
1633 EVT VT =
Op.getValueType();
1639 unsigned Opc =
Op.getOpcode();
1647 assert(PVT != VT &&
"Don't know what type to promote to!");
1657bool DAGCombiner::PromoteLoad(
SDValue Op) {
1658 if (!LegalOperations)
1664 EVT VT =
Op.getValueType();
1670 unsigned Opc =
Op.getOpcode();
1678 assert(PVT != VT &&
"Don't know what type to promote to!");
1683 EVT MemVT =
LD->getMemoryVT();
1685 :
LD->getExtensionType();
1687 LD->getChain(),
LD->getBasePtr(),
1688 MemVT,
LD->getMemOperand());
1697 AddToWorklist(
Result.getNode());
1698 recursivelyDeleteUnusedNodes(
N);
1711bool DAGCombiner::recursivelyDeleteUnusedNodes(
SDNode *
N) {
1712 if (!
N->use_empty())
1722 if (
N->use_empty()) {
1723 for (
const SDValue &ChildN :
N->op_values())
1724 Nodes.
insert(ChildN.getNode());
1726 removeFromWorklist(
N);
1731 }
while (!Nodes.
empty());
1746 WorklistInserter AddNodes(*
this);
1755 AddToWorklist(&
Node,
Node.use_empty());
1763 while (
SDNode *
N = getNextWorklistEntry()) {
1767 if (recursivelyDeleteUnusedNodes(
N))
1770 WorklistRemover DeadNodes(*
this);
1778 for (
SDNode *LN : UpdatedNodes)
1779 AddToWorklistWithUsers(LN);
1791 for (
const SDValue &ChildN :
N->op_values())
1792 AddToWorklist(ChildN.getNode(),
true,
1803 ChainsWithoutMergeableStores.
clear();
1814 "Node was deleted but visit returned new node!");
1822 N->getNumValues() == 1 &&
"Type mismatch");
1832 AddToWorklistWithUsers(RV.
getNode());
1838 recursivelyDeleteUnusedNodes(
N);
1848 switch (
N->getOpcode()) {
1874 case ISD::MUL:
return visitMUL<EmptyMatchContext>(
N);
1938 case ISD::FMA:
return visitFMA<EmptyMatchContext>(
N);
2010#define BEGIN_REGISTER_VP_SDNODE(SDOPC, ...) case ISD::SDOPC:
2011#include "llvm/IR/VPIntrinsics.def"
2012 return visitVPOp(
N);
2023 if (!DisableGenericCombines)
2029 "Node was deleted but visit returned NULL!");
2036 DagCombineInfo(DAG, Level,
false,
this);
2044 switch (
N->getOpcode()) {
2052 RV = PromoteIntBinOp(
SDValue(
N, 0));
2057 RV = PromoteIntShiftOp(
SDValue(
N, 0));
2078 if (N0 != N1 && (isa<ConstantSDNode>(N0) || !isa<ConstantSDNode>(N1))) {
2093 if (
unsigned NumOps =
N->getNumOperands()) {
2094 if (
N->getOperand(0).getValueType() == MVT::Other)
2095 return N->getOperand(0);
2096 if (
N->getOperand(NumOps-1).getValueType() == MVT::Other)
2097 return N->getOperand(NumOps-1);
2098 for (
unsigned i = 1; i < NumOps-1; ++i)
2099 if (
N->getOperand(i).getValueType() == MVT::Other)
2100 return N->getOperand(i);
2106 SDValue Operand =
N->getOperand(0);
2121 if (
N->getNumOperands() == 2) {
2123 return N->getOperand(0);
2125 return N->getOperand(1);
2140 AddToWorklist(*(
N->user_begin()));
2145 bool Changed =
false;
2152 for (
unsigned i = 0; i < TFs.
size(); ++i) {
2157 for (
unsigned j = i;
j < TFs.
size();
j++)
2168 switch (
Op.getOpcode()) {
2186 if (SeenOps.
insert(
Op.getNode()).second)
2197 for (
unsigned i = 1, e = TFs.
size(); i < e; i++)
2198 AddToWorklist(TFs[i]);
2210 bool DidPruneOps =
false;
2212 unsigned NumLeftToConsider = 0;
2214 Worklist.
push_back(std::make_pair(
Op.getNode(), NumLeftToConsider++));
2218 auto AddToWorklist = [&](
unsigned CurIdx,
SDNode *
Op,
unsigned OpNumber) {
2224 unsigned OrigOpNumber = 0;
2225 while (OrigOpNumber < Ops.size() && Ops[OrigOpNumber].getNode() !=
Op)
2227 assert((OrigOpNumber != Ops.size()) &&
2228 "expected to find TokenFactor Operand");
2230 for (
unsigned i = CurIdx + 1; i < Worklist.
size(); ++i) {
2231 if (Worklist[i].second == OrigOpNumber) {
2232 Worklist[i].second = OpNumber;
2235 OpWorkCount[OpNumber] += OpWorkCount[OrigOpNumber];
2236 OpWorkCount[OrigOpNumber] = 0;
2237 NumLeftToConsider--;
2240 if (SeenChains.
insert(
Op).second) {
2241 OpWorkCount[OpNumber]++;
2246 for (
unsigned i = 0; i < Worklist.
size() && i < 1024; ++i) {
2248 if (NumLeftToConsider <= 1)
2250 auto CurNode = Worklist[i].first;
2251 auto CurOpNumber = Worklist[i].second;
2252 assert((OpWorkCount[CurOpNumber] > 0) &&
2253 "Node should not appear in worklist");
2254 switch (CurNode->getOpcode()) {
2260 NumLeftToConsider++;
2263 for (
const SDValue &
Op : CurNode->op_values())
2264 AddToWorklist(i,
Op.getNode(), CurOpNumber);
2270 AddToWorklist(i, CurNode->getOperand(0).getNode(), CurOpNumber);
2273 if (
auto *MemNode = dyn_cast<MemSDNode>(CurNode))
2274 AddToWorklist(i, MemNode->getChain().getNode(), CurOpNumber);
2277 OpWorkCount[CurOpNumber]--;
2278 if (OpWorkCount[CurOpNumber] == 0)
2279 NumLeftToConsider--;
2293 if (SeenChains.
count(
Op.getNode()) == 0)
2308 WorklistRemover DeadNodes(*
this);
2314 AddUsersToWorklist(
N);
2319 }
while (!
N->use_empty());
2320 deleteAndRecombine(
N);
2328 return Const !=
nullptr && !Const->isOpaque() ? Const :
nullptr;
2338 Op =
N->getOperand(0);
2340 if (
N->getFlags().hasNoUnsignedWrap())
2345 if (
N.getValueType().getScalarType() != MVT::i1 ||
2362 if (LD->isIndexed() || LD->getBasePtr().getNode() !=
N)
2364 VT = LD->getMemoryVT();
2365 AS = LD->getAddressSpace();
2367 if (ST->isIndexed() || ST->getBasePtr().getNode() !=
N)
2369 VT = ST->getMemoryVT();
2370 AS = ST->getAddressSpace();
2372 if (LD->isIndexed() || LD->getBasePtr().getNode() !=
N)
2374 VT = LD->getMemoryVT();
2375 AS = LD->getAddressSpace();
2377 if (ST->isIndexed() || ST->getBasePtr().getNode() !=
N)
2379 VT = ST->getMemoryVT();
2380 AS = ST->getAddressSpace();
2395 }
else if (
N->getOpcode() ==
ISD::SUB) {
2417 bool ShouldCommuteOperands) {
2422 if (ShouldCommuteOperands)
2434 unsigned Opcode =
N->getOpcode();
2435 EVT VT =
N->getValueType(0);
2442 unsigned OpNo = ShouldCommuteOperands ? 0 : 1;
2460 "Unexpected binary operator");
2477 unsigned SelOpNo = 0;
2513 bool CanFoldNonConst =
2519 if (!CanFoldNonConst &&
2527 if (CanFoldNonConst) {
2564 "Expecting add or sub");
2569 bool IsAdd =
N->getOpcode() ==
ISD::ADD;
2570 SDValue C = IsAdd ?
N->getOperand(1) :
N->getOperand(0);
2571 SDValue Z = IsAdd ?
N->getOperand(0) :
N->getOperand(1);
2572 auto *CN = dyn_cast<ConstantSDNode>(
C);
2577 if (Z.getOperand(0).getValueType() != MVT::i1)
2589 EVT VT =
C.getValueType();
2602 if ((!LegalOperations || hasOperation(
ISD::AVGCEILU, VT)) &&
2607 if ((!LegalOperations || hasOperation(
ISD::AVGCEILS, VT)) &&
2620 "Expecting add or sub");
2624 bool IsAdd =
N->getOpcode() ==
ISD::ADD;
2625 SDValue ConstantOp = IsAdd ?
N->getOperand(1) :
N->getOperand(0);
2626 SDValue ShiftOp = IsAdd ?
N->getOperand(0) :
N->getOperand(1);
2648 {ConstantOp, DAG.getConstant(1, DL, VT)})) {
2650 Not.getOperand(0), ShAmt);
2692 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
2724 if ((!LegalOperations ||
2727 X.getScalarValueSizeInBits() == 1) {
2743 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
2747 if (!reassociationCanBreakAddressingModePattern(
ISD::ADD,
DL,
N, N0, N1)) {
2835 return (!Max && !
Op) ||
2836 (
Max &&
Op &&
Max->getAPIntValue() == (-
Op->getAPIntValue()));
2877 !
N->getFlags().hasNoSignedWrap()))) {
2898 (CA * CM + CB->getAPIntValue()).getSExtValue())) {
2902 if (
N->getFlags().hasNoUnsignedWrap() &&
2906 if (
N->getFlags().hasNoSignedWrap() &&
2915 DAG.
getConstant(CA * CM + CB->getAPIntValue(),
DL, VT), Flags);
2923 (CA * CM + CB->getAPIntValue()).getSExtValue())) {
2929 if (
N->getFlags().hasNoUnsignedWrap() &&
2934 if (
N->getFlags().hasNoSignedWrap() &&
2945 DAG.
getConstant(CA * CM + CB->getAPIntValue(),
DL, VT), Flags);
2950 if (
SDValue Combined = visitADDLikeCommutative(N0, N1,
N))
2953 if (
SDValue Combined = visitADDLikeCommutative(N1, N0,
N))
2985 if (
SDValue Combined = visitADDLike(
N))
3025 APInt NewStep = C0 + C1;
3035 APInt NewStep = SV0 + SV1;
3044 unsigned Opcode =
N->getOpcode();
3062 return DAG.
getNode(Opcode,
DL, VT, N1, N0);
3066 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
3086 bool ForceCarryReconstruction =
false) {
3092 V = V.getOperand(0);
3097 if (ForceCarryReconstruction)
3101 V = V.getOperand(0);
3105 if (ForceCarryReconstruction && V.getValueType() == MVT::i1)
3112 if (V.getResNo() != 1)
3119 EVT VT = V->getValueType(0);
3227 if (TN->
getVT() == MVT::i1) {
3244 DAG.
getVTList(VT, Carry.getValueType()), N0,
3257 if (!
N->hasAnyUseOfValue(1))
3290 if (Force && isa<ConstantSDNode>(V))
3297 return V.getOperand(0);
3309 EVT CarryVT =
N->getValueType(1);
3313 if (!
N->hasAnyUseOfValue(1))
3320 return DAG.
getNode(
N->getOpcode(),
DL,
N->getVTList(), N1, N0);
3345 if (
SDValue Combined = visitUADDOLike(N0, N1,
N))
3348 if (
SDValue Combined = visitUADDOLike(N1, N0,
N))
3382 SDValue CarryIn =
N->getOperand(2);
3401 SDValue CarryIn =
N->getOperand(2);
3412 if (!LegalOperations ||
3422 AddToWorklist(CarryExt.
getNode());
3428 if (
SDValue Combined = visitUADDO_CARRYLike(N0, N1, CarryIn,
N))
3431 if (
SDValue Combined = visitUADDO_CARRYLike(N1, N0, CarryIn,
N))
3439 SDValue Ops[] = {N1, N0, CarryIn};
3578 EVT CarryOutType =
N->getValueType(0);
3594 unsigned CarryInOperandNum =
3596 if (Opcode ==
ISD::USUBO && CarryInOperandNum != 1)
3690 SDValue CarryIn =
N->getOperand(2);
3701 if (!LegalOperations ||
3706 if (
SDValue Combined = visitSADDO_CARRYLike(N0, N1, CarryIn,
N))
3709 if (
SDValue Combined = visitSADDO_CARRYLike(N1, N0, CarryIn,
N))
3721 "Illegal truncation");
3747 !(!LegalOperations || hasOperation(
ISD::USUBSAT, DstVT)))
3750 EVT SubVT =
N->getValueType(0);
3818template <
class MatchContextClass>
3841 if ((
BitWidth - Src.getValueType().getScalarSizeInBits()) != BitWidthDiff)
3851 if (!(AndMask.
isMask(AndMaskWidth) && XorMask.
countr_one() >= AndMaskWidth))
3882 auto PeekThroughFreeze = [](
SDValue N) {
3884 return N->getOperand(0);
3888 if (
SDValue V = foldSubCtlzNot<EmptyMatchContext>(
N, DAG))
3893 if (PeekThroughFreeze(N0) == PeekThroughFreeze(N1))
3902 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
3910 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
3933 if (
N->getFlags().hasNoUnsignedWrap())
3939 if (
N->getFlags().hasNoSignedWrap())
3965 if (hasOperation(NewOpc, VT))
4092 if (!reassociationCanBreakAddressingModePattern(
ISD::SUB,
DL,
N, N0, N1) &&
4130 if ((!LegalOperations || hasOperation(
ISD::ABS, VT)) &&
4140 if (GA->getGlobal() == GB->getGlobal())
4148 if (TN->
getVT() == MVT::i1) {
4201 DAG.
getVTList(VT, Carry.getValueType()), NegX, Zero,
4209 if (!C0->isOpaque()) {
4210 const APInt &C0Val = C0->getAPIntValue();
4211 const APInt &MaybeOnes = ~DAG.computeKnownBits(N1).Zero;
4212 if ((C0Val - MaybeOnes) == (C0Val ^ MaybeOnes))
4218 if ((!LegalOperations || hasOperation(
ISD::ABDS, VT)) &&
4230 if ((!LegalOperations || hasOperation(
ISD::ABDU, VT)) &&
4245 unsigned Opcode =
N->getOpcode();
4266 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4292 if (!
N->hasAnyUseOfValue(1))
4319 EVT CarryVT =
N->getValueType(1);
4323 if (!
N->hasAnyUseOfValue(1))
4358 SDValue CarryIn =
N->getOperand(2);
4370 SDValue CarryIn =
N->getOperand(2);
4374 if (!LegalOperations ||
4385 SDValue CarryIn =
N->getOperand(2);
4389 if (!LegalOperations ||
4421template <
class MatchContextClass>
SDValue DAGCombiner::visitMUL(
SDNode *
N) {
4427 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
4428 MatchContextClass Matcher(DAG, TLI,
N);
4441 return Matcher.getNode(
ISD::MUL,
DL, VT, N1, N0);
4443 bool N1IsConst =
false;
4444 bool N1IsOpaqueConst =
false;
4451 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4456 "Splat APInt should be element width");
4458 N1IsConst = isa<ConstantSDNode>(N1);
4461 N1IsOpaqueConst = cast<ConstantSDNode>(N1)->isOpaque();
4466 if (N1IsConst && ConstValue1.
isZero())
4470 if (N1IsConst && ConstValue1.
isOne())
4474 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4478 if (N1IsConst && ConstValue1.
isAllOnes())
4484 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
4493 unsigned Log2Val = (-ConstValue1).logBase2();
4497 return Matcher.getNode(
4511 if (LoHi->hasAnyUseOfValue(1))
4514 if (LoHi->hasAnyUseOfValue(1))
4535 if (!UseVP && N1IsConst &&
4543 unsigned TZeros = MulC == 2 ? 0 : MulC.
countr_zero();
4545 if ((MulC - 1).isPowerOf2())
4547 else if ((MulC + 1).isPowerOf2())
4552 MathOp ==
ISD::ADD ? (MulC - 1).logBase2() : (MulC + 1).logBase2();
4555 "multiply-by-constant generated out of bounds shift");
4559 TZeros ? DAG.
getNode(MathOp,
DL, VT, Shl,
4601 return Matcher.getNode(
4619 APInt NewStep = C0 * MulVal;
4625 if (!UseVP && (!LegalOperations || hasOperation(
ISD::ABS, VT)) &&
4642 if (!V ||
V->isZero()) {
4656 for (
unsigned I = 0;
I != NumElts; ++
I)
4687 EVT NodeType =
Node->getValueType(0);
4688 if (!NodeType.isSimple())
4690 switch (NodeType.getSimpleVT().SimpleTy) {
4691 default:
return false;
4692 case MVT::i8: LC=
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
4693 case MVT::i16: LC=
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
4694 case MVT::i32: LC=
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
4695 case MVT::i64: LC=
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
4696 case MVT::i128: LC=
isSigned ? RTLIB::SDIVREM_I128:RTLIB::UDIVREM_I128;
break;
4704 if (
Node->use_empty())
4707 unsigned Opcode =
Node->getOpcode();
4712 EVT VT =
Node->getValueType(0);
4726 unsigned OtherOpcode = 0;
4747 unsigned UserOpc =
User->getOpcode();
4748 if ((UserOpc == Opcode || UserOpc == OtherOpcode || UserOpc == DivRemOpc) &&
4752 if (UserOpc == OtherOpcode) {
4755 }
else if (UserOpc == DivRemOpc) {
4758 assert(UserOpc == Opcode);
4763 CombineTo(
User, combined);
4774 EVT VT =
N->getValueType(0);
4777 unsigned Opc =
N->getOpcode();
4786 if (DAG.
isUndef(Opc, {N0, N1}))
4797 if (N0C && N0C->
isZero())
4820 EVT VT =
N->getValueType(0);
4830 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4847 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4855 if (
SDValue V = visitSDIVLike(N0, N1,
N)) {
4862 AddToWorklist(
Mul.getNode());
4864 CombineTo(RemNode, Sub);
4884 if (
C->isZero() ||
C->isOpaque())
4886 if (
C->getAPIntValue().isPowerOf2())
4888 if (
C->getAPIntValue().isNegatedPowerOf2())
4898 EVT VT =
N->getValueType(0);
4923 AddToWorklist(Sign.
getNode());
4929 AddToWorklist(
Add.getNode());
4940 Sra = DAG.
getSelect(
DL, VT, IsOneOrAllOnes, N0, Sra);
4968 EVT VT =
N->getValueType(0);
4978 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4992 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4995 if (
SDValue V = visitUDIVLike(N0, N1,
N)) {
5002 AddToWorklist(
Mul.getNode());
5004 CombineTo(RemNode, Sub);
5028 EVT VT =
N->getValueType(0);
5032 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
5033 AddToWorklist(LogBase2.getNode());
5037 AddToWorklist(Trunc.
getNode());
5046 if (
SDValue LogBase2 = BuildLogBase2(N10,
DL)) {
5047 AddToWorklist(LogBase2.getNode());
5051 AddToWorklist(Trunc.
getNode());
5053 AddToWorklist(
Add.getNode());
5081 unsigned Opcode =
N->getOpcode();
5084 EVT VT =
N->getValueType(0);
5106 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
5119 AddToWorklist(
Add.getNode());
5130 AddToWorklist(
Add.getNode());
5147 if (
SDValue OptimizedRem = buildOptimizedSREM(N0, N1,
N))
5148 return OptimizedRem;
5152 isSigned ? visitSDIVLike(N0, N1,
N) : visitUDIVLike(N0, N1,
N);
5158 CombineTo(DivNode, OptimizedDiv);
5161 AddToWorklist(OptimizedDiv.
getNode());
5162 AddToWorklist(
Mul.getNode());
5169 return DivRem.getValue(1);
5177 EVT VT =
N->getValueType(0);
5190 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5218 unsigned SimpleSize =
Simple.getSizeInBits();
5236 EVT VT =
N->getValueType(0);
5249 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5273 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
5288 unsigned SimpleSize =
Simple.getSizeInBits();
5310 unsigned Opcode =
N->getOpcode();
5313 EVT VT =
N->getValueType(0);
5324 return DAG.
getNode(Opcode,
DL,
N->getVTList(), N1, N0);
5327 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5353 X.getValueType() ==
Y.getValueType() &&
5354 hasOperation(Opcode,
X.getValueType())) {
5360 X.getValueType() ==
Y.getValueType() &&
5361 hasOperation(Opcode,
X.getValueType())) {
5394 if (IsSigned &&
Add->getFlags().hasNoSignedWrap())
5397 if (!IsSigned &&
Add->getFlags().hasNoUnsignedWrap())
5406 unsigned Opcode =
N->getOpcode();
5409 EVT VT =
N->getValueType(0);
5419 return DAG.
getNode(Opcode,
DL,
N->getVTList(), N1, N0);
5422 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5437 (!LegalOperations || hasOperation(
ISD::ABS, VT)))
5455SDValue DAGCombiner::SimplifyNodeWithTwoResults(
SDNode *
N,
unsigned LoOp,
5458 bool HiExists =
N->hasAnyUseOfValue(1);
5459 if (!HiExists && (!LegalOperations ||
5462 return CombineTo(
N, Res, Res);
5466 bool LoExists =
N->hasAnyUseOfValue(0);
5467 if (!LoExists && (!LegalOperations ||
5470 return CombineTo(
N, Res, Res);
5474 if (LoExists && HiExists)
5480 AddToWorklist(
Lo.getNode());
5483 (!LegalOperations ||
5485 return CombineTo(
N, LoOpt, LoOpt);
5490 AddToWorklist(
Hi.getNode());
5493 (!LegalOperations ||
5495 return CombineTo(
N, HiOpt, HiOpt);
5507 EVT VT =
N->getValueType(0);
5511 if (isa<ConstantSDNode>(N0) && isa<ConstantSDNode>(N1))
5523 unsigned SimpleSize =
Simple.getSizeInBits();
5535 return CombineTo(
N,
Lo,
Hi);
5548 EVT VT =
N->getValueType(0);
5552 if (isa<ConstantSDNode>(N0) && isa<ConstantSDNode>(N1))
5563 return CombineTo(
N, Zero, Zero);
5569 return CombineTo(
N, N0, Zero);
5576 unsigned SimpleSize =
Simple.getSizeInBits();
5588 return CombineTo(
N,
Lo,
Hi);
5601 EVT CarryVT =
N->getValueType(1);
5622 return DAG.
getNode(
N->getOpcode(),
DL,
N->getVTList(), N1, N0);
5634 N->getVTList(), N0, N0);
5641 return CombineTo(
N,
And, Cmp);
5679 unsigned Opcode0 = isSignedMinMax(N0, N1, N2, N3,
CC);
5717 N0CC = cast<CondCodeSDNode>(N0.
getOperand(4))->get();
5733 unsigned Opcode1 = isSignedMinMax(N00, N01, N02, N03, N0CC);
5734 if (!Opcode1 || Opcode0 == Opcode1)
5744 APInt MinCPlus1 = MinC + 1;
5745 if (-MaxC == MinCPlus1 && MinCPlus1.
isPowerOf2()) {
5802 unsigned BW = (C1 + 1).exactLogBase2();
5822 unsigned Opcode =
N->getOpcode();
5836 return DAG.
getNode(Opcode,
DL, VT, N1, N0);
5840 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5844 if (
SDValue RMINMAX = reassociateOps(Opcode,
DL, N0, N1,
N->getFlags()))
5864 return DAG.
getNode(AltOpcode,
DL, VT, N0, N1);
5876 auto ReductionOpcode = [](
unsigned Opcode) {
5890 if (
SDValue SD = reassociateReduction(ReductionOpcode(Opcode), Opcode,
5904 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
5906 unsigned LogicOpcode =
N->getOpcode();
5921 EVT XVT =
X.getValueType();
5931 if (XVT !=
Y.getValueType())
5935 if ((VT.
isVector() || LegalOperations) &&
5948 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
5958 if (XVT !=
Y.getValueType())
5970 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
5991 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6006 return DAG.
getNode(HandOpcode,
DL, VT, Logic0, Logic1, S);
6019 if (XVT.
isInteger() && XVT ==
Y.getValueType() &&
6023 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6040 auto *SVN0 = cast<ShuffleVectorSDNode>(N0);
6041 auto *SVN1 = cast<ShuffleVectorSDNode>(N1);
6042 assert(
X.getValueType() ==
Y.getValueType() &&
6043 "Inputs to shuffles are not the same type");
6049 if (!SVN0->hasOneUse() || !SVN1->hasOneUse() ||
6050 !SVN0->getMask().equals(SVN1->getMask()))
6086 SDValue LL, LR, RL, RR, N0CC, N1CC;
6087 if (!isSetCCEquivalent(N0, LL, LR, N0CC) ||
6088 !isSetCCEquivalent(N1, RL, RR, N1CC))
6092 "Unexpected operand types for bitwise logic op");
6095 "Unexpected operand types for setcc");
6111 if (LR == RR && CC0 == CC1 && IsInteger) {
6116 bool AndEqZero = IsAnd && CC1 ==
ISD::SETEQ && IsZero;
6118 bool AndGtNeg1 = IsAnd && CC1 ==
ISD::SETGT && IsNeg1;
6120 bool OrNeZero = !IsAnd && CC1 ==
ISD::SETNE && IsZero;
6122 bool OrLtZero = !IsAnd && CC1 ==
ISD::SETLT && IsZero;
6128 if (AndEqZero || AndGtNeg1 || OrNeZero || OrLtZero) {
6130 AddToWorklist(
Or.getNode());
6135 bool AndEqNeg1 = IsAnd && CC1 ==
ISD::SETEQ && IsNeg1;
6137 bool AndLtZero = IsAnd && CC1 ==
ISD::SETLT && IsZero;
6139 bool OrNeNeg1 = !IsAnd && CC1 ==
ISD::SETNE && IsNeg1;
6141 bool OrGtNeg1 = !IsAnd && CC1 ==
ISD::SETGT && IsNeg1;
6147 if (AndEqNeg1 || AndLtZero || OrNeNeg1 || OrGtNeg1) {
6149 AddToWorklist(
And.getNode());
6163 AddToWorklist(
Add.getNode());
6190 return !C0->
isOpaque() && !C1->isOpaque() && (CMax - CMin).isPowerOf2();
6208 if (LL == RR && LR == RL) {
6215 if (LL == RL && LR == RR) {
6219 (!LegalOperations ||
6242 bool isFMAXNUMFMINNUM_IEEE,
6243 bool isFMAXNUMFMINNUM) {
6254 isFMAXNUMFMINNUM_IEEE
6262 isFMAXNUMFMINNUM_IEEE
6280 isFMAXNUMFMINNUM_IEEE
6289 isFMAXNUMFMINNUM_IEEE
6299 "Invalid Op to combine SETCC with");
6310 LogicOp,
LHS.getNode(),
RHS.getNode());
6345 (isFMAXNUMFMINNUM_IEEE || isFMAXNUMFMINNUM))) &&
6351 SDValue CommonValue, Operand1, Operand2;
6359 }
else if (LHS1 == RHS1) {
6372 }
else if (RHS0 == LHS1) {
6389 bool IsSigned = isSignedIntSetCC(
CC);
6401 DAG, isFMAXNUMFMINNUM_IEEE, isFMAXNUMFMINNUM);
6405 DAG.
getNode(NewOpcode,
DL, OpVT, Operand1, Operand2);
6406 return DAG.
getSetCC(
DL, VT, MinMaxValue, CommonValue,
CC);
6416 LHS0 == RHS0 && LHS1C && RHS1C && OpVT.
isInteger()) {
6417 const APInt &APLhs = LHS1C->getAPIntValue();
6418 const APInt &APRhs = RHS1C->getAPIntValue();
6422 if (APLhs == (-APRhs) &&
6433 }
else if (TargetPreference &
6454 APInt Dif = MaxC - MinC;
6488 EVT CondVT =
Cond.getValueType();
6499 EVT OpVT =
T.getValueType();
6518 if (
SDValue V = foldLogicOfSetCCs(
true, N0, N1,
DL))
6536 APInt SRLC = SRLI->getAPIntValue();
6548 CombineTo(N0.
getNode(), NewAdd);
6562 EVT LoadResultTy,
EVT &ExtVT) {
6571 if (ExtVT == LoadedVT &&
6572 (!LegalOperations ||
6588 if (LegalOperations &&
6624 if (LdStMemVT.
bitsLT(MemVT))
6629 assert(ShAmt % 8 == 0 &&
"ShAmt is byte offset");
6630 const unsigned ByteShAmt = ShAmt / 8;
6641 if (PtrType == MVT::Untyped || PtrType.
isExtended())
6644 if (isa<LoadSDNode>(LDST)) {
6648 if (!
SDValue(Load, 0).hasOneUse())
6651 if (LegalOperations &&
6660 if (
Load->getNumValues() > 2)
6673 assert(isa<StoreSDNode>(LDST) &&
"It is not a Load nor a Store SDNode");
6679 if (LegalOperations &&
6686bool DAGCombiner::SearchForAndLoads(
SDNode *
N,
6694 if (
Op.getValueType().isVector())
6698 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
6700 (
Mask->getAPIntValue() &
C->getAPIntValue()) !=
C->getAPIntValue())
6705 if (!
Op.hasOneUse())
6708 switch(
Op.getOpcode()) {
6710 auto *
Load = cast<LoadSDNode>(
Op);
6712 if (isAndLoadExtLoad(Mask, Load,
Load->getValueType(0), ExtVT) &&
6730 unsigned ActiveBits =
Mask->getAPIntValue().countr_one();
6733 cast<VTSDNode>(
Op.getOperand(1))->getVT() :
6734 Op.getOperand(0).getValueType();
6745 if (!SearchForAndLoads(
Op.getNode(), Loads, NodesWithConsts, Mask,
6756 NodeToMask =
Op.getNode();
6759 for (
unsigned i = 0, e = NodeToMask->
getNumValues(); i < e; ++i) {
6761 if (VT != MVT::Glue && VT != MVT::Other) {
6763 NodeToMask =
nullptr;
6775bool DAGCombiner::BackwardsPropagateMask(
SDNode *
N) {
6776 auto *
Mask = dyn_cast<ConstantSDNode>(
N->getOperand(1));
6780 if (!
Mask->getAPIntValue().isMask())
6784 if (isa<LoadSDNode>(
N->getOperand(0)))
6789 SDNode *FixupNode =
nullptr;
6790 if (SearchForAndLoads(
N, Loads, NodesWithConsts, Mask, FixupNode)) {
6803 SDValue(FixupNode, 0), MaskOp);
6805 if (
And.getOpcode() == ISD ::AND)
6810 for (
auto *LogicN : NodesWithConsts) {
6814 if (isa<ConstantSDNode>(Op0))
6818 if (isa<ConstantSDNode>(Op1))
6822 if (isa<ConstantSDNode>(Op0) && !isa<ConstantSDNode>(Op1))
6829 for (
auto *Load : Loads) {
6834 if (
And.getOpcode() == ISD ::AND)
6837 SDValue NewLoad = reduceLoadWidth(
And.getNode());
6839 "Shouldn't be masking the load if it can't be narrowed");
6840 CombineTo(Load, NewLoad, NewLoad.
getValue(1));
6853SDValue DAGCombiner::unfoldExtremeBitClearingToShifts(
SDNode *
N) {
6864 unsigned OuterShift;
6865 unsigned InnerShift;
6867 auto matchMask = [&OuterShift, &InnerShift, &
Y](
SDValue M) ->
bool {
6870 OuterShift =
M->getOpcode();
6879 Y =
M->getOperand(1);
6886 else if (matchMask(N0))
6892 EVT VT =
N->getValueType(0);
6909 SDValue And0 =
And->getOperand(0), And1 =
And->getOperand(1);
6919 bool FoundNot =
false;
6922 Src = Src.getOperand(0);
6928 Src = Src.getOperand(0);
6932 if (Src.getOpcode() !=
ISD::SRL || !Src.hasOneUse())
6936 EVT SrcVT = Src.getValueType();
6943 SDValue ShiftAmt = Src.getOperand(1);
6944 auto *ShiftAmtC = dyn_cast<ConstantSDNode>(ShiftAmt);
6945 if (!ShiftAmtC || !ShiftAmtC->getAPIntValue().ult(
BitWidth))
6949 Src = Src.getOperand(0);
6956 Src = Src.getOperand(0);
6980 EVT VT =
N->getValueType(0);
7006 unsigned LogicOpcode =
N->getOpcode();
7008 "Expected bitwise logic operation");
7014 unsigned ShiftOpcode = ShiftOp.
getOpcode();
7015 if (LogicOp.
getOpcode() != LogicOpcode ||
7039 EVT VT =
N->getValueType(0);
7043 return DAG.
getNode(LogicOpcode,
DL, VT, NewShift, Z);
7054 unsigned LogicOpcode =
N->getOpcode();
7056 "Expected bitwise logic operation");
7057 if (LeftHand.
getOpcode() != LogicOpcode ||
7078 EVT VT =
N->getValueType(0);
7080 return DAG.
getNode(LogicOpcode,
DL, VT, CombinedShifts, W);
7107 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
7121 auto *MLoad = dyn_cast<MaskedLoadSDNode>(N0);
7124 EVT LoadVT = MLoad->getMemoryVT();
7132 if (
Splat->getAPIntValue().isMask(ElementSize)) {
7134 ExtVT,
DL, MLoad->getChain(), MLoad->getBasePtr(),
7135 MLoad->getOffset(), MLoad->getMask(), MLoad->getPassThru(),
7136 LoadVT, MLoad->getMemOperand(), MLoad->getAddressingMode(),
7138 bool LoadHasOtherUsers = !N0.
hasOneUse();
7139 CombineTo(
N, NewLoad);
7140 if (LoadHasOtherUsers)
7161 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
7175 return RHS->getAPIntValue().isSubsetOf(
LHS->getAPIntValue());
7243 unsigned EltBitWidth =
Vector->getValueType(0).getScalarSizeInBits();
7244 APInt SplatValue, SplatUndef;
7245 unsigned SplatBitSize;
7252 const bool IsBigEndian =
false;
7254 Vector->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
7255 HasAnyUndefs, EltBitWidth, IsBigEndian);
7259 if (IsSplat && (SplatBitSize % EltBitWidth) == 0) {
7262 SplatValue |= SplatUndef;
7269 for (
unsigned i = 0, n = (SplatBitSize / EltBitWidth); i < n; ++i)
7278 Load->getValueType(0),
7279 Load->getMemoryVT());
7287 switch (
Load->getExtensionType()) {
7288 default:
B =
false;
break;
7300 CombineTo(
N, (N0.
getNode() == Load) ? NewLoad : N0);
7305 Load->getChain(),
Load->getBasePtr(),
7306 Load->getOffset(),
Load->getMemoryVT(),
7307 Load->getMemOperand());
7309 if (
Load->getNumValues() == 3) {
7313 CombineTo(Load, To, 3,
true);
7315 CombineTo(Load, NewLoad.getValue(0), NewLoad.getValue(1));
7325 if (
SDValue Shuffle = XformToShuffleWithZero(
N))
7334 EVT ExtVT =
Ext->getValueType(0);
7351 if (
auto *GN0 = dyn_cast<MaskedGatherSDNode>(N0)) {
7352 EVT MemVT = GN0->getMemoryVT();
7355 if (
SDValue(GN0, 0).hasOneUse() &&
7358 SDValue Ops[] = {GN0->getChain(), GN0->getPassThru(), GN0->getMask(),
7359 GN0->getBasePtr(), GN0->getIndex(), GN0->getScale()};
7362 DAG.
getVTList(VT, MVT::Other), MemVT,
DL, Ops, GN0->getMemOperand(),
7365 CombineTo(
N, ZExtLoad);
7366 AddToWorklist(ZExtLoad.
getNode());
7375 if (
SDValue Res = reduceLoadWidth(
N))
7383 if (BackwardsPropagateMask(
N))
7387 if (
SDValue Combined = visitANDLike(N0, N1,
N))
7392 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
7439 X.getOperand(0).getScalarValueSizeInBits() == 1)
7442 X.getOperand(0).getScalarValueSizeInBits() == 1)
7456 auto *LN0 = cast<LoadSDNode>(N0);
7457 EVT MemVT = LN0->getMemoryVT();
7464 ((!LegalOperations && LN0->isSimple()) ||
7468 LN0->getBasePtr(), MemVT, LN0->getMemOperand());
7482 if (
SDValue Shifts = unfoldExtremeBitClearingToShifts(
N))
7498 auto *
C = dyn_cast<ConstantSDNode>(RHS);
7502 if (!
C->getAPIntValue().isMask(
7503 LHS.getOperand(0).getValueType().getFixedSizeInBits()))
7510 if (IsAndZeroExtMask(N0, N1))
7519 if (LegalOperations || VT.
isVector())
7528 bool DemandHighBits) {
7529 if (!LegalOperations)
7532 EVT VT =
N->getValueType(0);
7533 if (VT != MVT::i64 && VT != MVT::i32 && VT != MVT::i16)
7539 bool LookPassAnd0 =
false;
7540 bool LookPassAnd1 =
false;
7555 LookPassAnd0 =
true;
7565 LookPassAnd1 =
true;
7591 LookPassAnd0 =
true;
7605 LookPassAnd1 =
true;
7614 if (OpSizeInBits > 16) {
7618 if (DemandHighBits && !LookPassAnd0)
7625 if (!LookPassAnd1) {
7626 unsigned HighBit = DemandHighBits ? OpSizeInBits : 24;
7634 if (OpSizeInBits > 16) {
7649 if (!
N->hasOneUse())
7652 unsigned Opc =
N.getOpcode();
7664 N1C = dyn_cast<ConstantSDNode>(
N.getOperand(1));
7666 N1C = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
7670 unsigned MaskByteOffset;
7674 case 0xFF: MaskByteOffset = 0;
break;
7675 case 0xFF00: MaskByteOffset = 1;
break;
7684 case 0xFF0000: MaskByteOffset = 2;
break;
7685 case 0xFF000000: MaskByteOffset = 3;
break;
7690 if (MaskByteOffset == 0 || MaskByteOffset == 2) {
7696 if (!
C ||
C->getZExtValue() != 8)
7704 if (!
C ||
C->getZExtValue() != 8)
7710 if (MaskByteOffset != 0 && MaskByteOffset != 2)
7713 if (!
C ||
C->getZExtValue() != 8)
7718 if (MaskByteOffset != 1 && MaskByteOffset != 3)
7721 if (!
C ||
C->getZExtValue() != 8)
7725 if (Parts[MaskByteOffset])
7740 if (!
C ||
C->getAPIntValue() != 16)
7742 Parts[0] = Parts[1] =
N.getOperand(0).getOperand(0).getNode();
7757 "MatchBSwapHWordOrAndAnd: expecting i32");
7767 if (!Mask0 || !Mask1)
7778 if (!ShiftAmt0 || !ShiftAmt1)
7798 if (!LegalOperations)
7801 EVT VT =
N->getValueType(0);
7839 if (Parts[0] != Parts[1] || Parts[0] != Parts[2] || Parts[0] != Parts[3])
7867 if (
SDValue V = foldLogicOfSetCCs(
false, N0, N1,
DL))
7882 const APInt &LHSMask = N0O1C->getAPIntValue();
7883 const APInt &RHSMask = N1O1C->getAPIntValue();
7917 auto peekThroughResize = [](
SDValue V) {
7919 return V->getOperand(0);
7923 SDValue N0Resized = peekThroughResize(N0);
7925 SDValue N1Resized = peekThroughResize(N1);
7930 if (N00 == N1Resized || N01 == N1Resized)
7937 if (peekThroughResize(NotOperand) == N1Resized)
7945 if (peekThroughResize(NotOperand) == N1Resized)
7966 auto peekThroughZext = [](
SDValue V) {
7968 return V->getOperand(0);
7990 Lo.getScalarValueSizeInBits() == (BW / 2) &&
7991 Lo.getValueType() ==
Hi.getValueType()) {
8028 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
8042 auto *SV0 = dyn_cast<ShuffleVectorSDNode>(N0);
8043 auto *SV1 = dyn_cast<ShuffleVectorSDNode>(N1);
8050 if ((ZeroN00 != ZeroN01) && (ZeroN10 != ZeroN11)) {
8051 assert((!ZeroN00 || !ZeroN01) &&
"Both inputs zero!");
8052 assert((!ZeroN10 || !ZeroN11) &&
"Both inputs zero!");
8053 bool CanFold =
true;
8057 for (
int i = 0; i != NumElts; ++i) {
8058 int M0 = SV0->getMaskElt(i);
8059 int M1 = SV1->getMaskElt(i);
8062 bool M0Zero =
M0 < 0 || (ZeroN00 == (
M0 < NumElts));
8063 bool M1Zero =
M1 < 0 || (ZeroN10 == (
M1 < NumElts));
8067 if ((M0Zero &&
M1 < 0) || (M1Zero &&
M0 < 0))
8071 if (M0Zero == M1Zero) {
8076 assert((
M0 >= 0 ||
M1 >= 0) &&
"Undef index!");
8082 Mask[i] = M1Zero ?
M0 % NumElts : (
M1 % NumElts) + NumElts;
8091 return LegalShuffle;
8105 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
8116 if (
SDValue Combined = visitORLike(N0, N1,
DL))
8123 if (
SDValue BSwap = MatchBSwapHWord(
N, N0, N1))
8125 if (
SDValue BSwap = MatchBSwapHWordLow(
N, N0, N1))
8159 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
8163 if (
SDValue Rot = MatchRotate(N0, N1,
DL))
8166 if (
SDValue Load = MatchLoadCombine(
N))
8176 if (
SDValue Combined = visitADDLike(
N))
8181 if (LegalOperations || VT.
isVector())
8192 Mask =
Op.getOperand(1);
8193 return Op.getOperand(0);
8236 assert(OppShift && ExtractFrom &&
"Empty SDValue");
8264 bool IsMulOrDiv =
false;
8267 auto SelectOpcode = [&](
unsigned NeededShift,
unsigned MulOrDivVariant) {
8268 IsMulOrDiv = ExtractFrom.
getOpcode() == MulOrDivVariant;
8269 if (!IsMulOrDiv && ExtractFrom.
getOpcode() != NeededShift)
8271 Opcode = NeededShift;
8321 if (Rem != 0 || ResultAmt != OppLHSAmt)
8327 if (OppLHSAmt != ExtractFromAmt - NeededShiftAmt.
zextOrTrunc(
8336 return DAG.
getNode(Opcode,
DL, ResVT, OppShiftLHS, NewShiftNode);
8390 unsigned MaskLoBits = 0;
8392 unsigned Bits =
Log2_64(EltSize);
8394 if (NegBits >= Bits) {
8417 if (PosBits >= MaskLoBits) {
8439 if ((Pos == NegOp1) ||
8463 return Width.
getLoBits(MaskLoBits) == 0;
8464 return Width == EltSize;
8474 SDValue InnerNeg,
bool HasPos,
8475 unsigned PosOpcode,
unsigned NegOpcode,
8487 return DAG.
getNode(HasPos ? PosOpcode : NegOpcode,
DL, VT, Shifted,
8488 HasPos ? Pos : Neg);
8502 SDValue InnerNeg,
bool HasPos,
8503 unsigned PosOpcode,
unsigned NegOpcode,
8515 if (
matchRotateSub(InnerPos, InnerNeg, EltBits, DAG, N0 == N1)) {
8516 return DAG.
getNode(HasPos ? PosOpcode : NegOpcode,
DL, VT, N0, N1,
8517 HasPos ? Pos : Neg);
8524 auto IsBinOpImm = [](
SDValue Op,
unsigned BinOpc,
unsigned Imm) {
8525 if (
Op.getOpcode() != BinOpc)
8534 IsBinOpImm(InnerNeg,
ISD::XOR, EltBits - 1) &&
8543 IsBinOpImm(InnerPos,
ISD::XOR, EltBits - 1) &&
8553 IsBinOpImm(InnerPos,
ISD::XOR, EltBits - 1) &&
8568 EVT VT =
LHS.getValueType();
8573 bool HasROTL = hasOperation(
ISD::ROTL, VT);
8574 bool HasROTR = hasOperation(
ISD::ROTR, VT);
8575 bool HasFSHL = hasOperation(
ISD::FSHL, VT);
8576 bool HasFSHR = hasOperation(
ISD::FSHR, VT);
8587 if (LegalOperations && !HasROTL && !HasROTR && !HasFSHL && !HasFSHR)
8592 LHS.getOperand(0).getValueType() ==
RHS.getOperand(0).getValueType()) {
8594 if (
SDValue Rot = MatchRotate(
LHS.getOperand(0),
RHS.getOperand(0),
DL)) {
8609 if (!LHSShift && !RHSShift)
8624 RHSShift = NewRHSShift;
8629 LHSShift = NewLHSShift;
8632 if (!RHSShift || !LHSShift)
8659 return (
LHS->getAPIntValue() +
RHS->getAPIntValue()) == EltSizeInBits;
8662 auto ApplyMasks = [&](
SDValue Res) {
8686 bool IsRotate = LHSShiftArg == RHSShiftArg;
8687 if (!IsRotate && !(HasFSHL || HasFSHR)) {
8696 if (CommonOp ==
Or.getOperand(0)) {
8698 Y =
Or.getOperand(1);
8701 if (CommonOp ==
Or.getOperand(1)) {
8703 Y =
Or.getOperand(0);
8710 if (matchOr(LHSShiftArg, RHSShiftArg)) {
8715 }
else if (matchOr(RHSShiftArg, LHSShiftArg)) {
8724 return ApplyMasks(Res);
8737 if (IsRotate && (HasROTL || HasROTR || !(HasFSHL || HasFSHR))) {
8738 bool UseROTL = !LegalOperations || HasROTL;
8740 UseROTL ? LHSShiftAmt : RHSShiftAmt);
8742 bool UseFSHL = !LegalOperations || HasFSHL;
8744 RHSShiftArg, UseFSHL ? LHSShiftAmt : RHSShiftAmt);
8747 return ApplyMasks(Res);
8752 if (!HasROTL && !HasROTR && !HasFSHL && !HasFSHR)
8761 SDValue LExtOp0 = LHSShiftAmt;
8762 SDValue RExtOp0 = RHSShiftAmt;
8775 if (IsRotate && (HasROTL || HasROTR)) {
8777 MatchRotatePosNeg(LHSShiftArg, LHSShiftAmt, RHSShiftAmt, LExtOp0,
8783 MatchRotatePosNeg(RHSShiftArg, RHSShiftAmt, LHSShiftAmt, RExtOp0,
8790 MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, LHSShiftAmt, RHSShiftAmt,
8796 MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, RHSShiftAmt, LHSShiftAmt,
8847static std::optional<SDByteProvider>
8849 std::optional<uint64_t> VectorIndex,
8850 unsigned StartingIndex = 0) {
8854 return std::nullopt;
8858 if (
Depth && !
Op.hasOneUse() &&
8859 (
Op.getOpcode() !=
ISD::LOAD || !
Op.getValueType().isVector()))
8860 return std::nullopt;
8864 if (
Op.getOpcode() !=
ISD::LOAD && VectorIndex.has_value())
8865 return std::nullopt;
8869 return std::nullopt;
8871 assert(Index < ByteWidth &&
"invalid index requested");
8874 switch (
Op.getOpcode()) {
8879 return std::nullopt;
8883 return std::nullopt;
8885 if (
LHS->isConstantZero())
8887 if (
RHS->isConstantZero())
8889 return std::nullopt;
8892 auto ShiftOp = dyn_cast<ConstantSDNode>(
Op->getOperand(1));
8894 return std::nullopt;
8896 uint64_t BitShift = ShiftOp->getZExtValue();
8898 if (BitShift % 8 != 0)
8899 return std::nullopt;
8905 return Index < ByteShift
8908 Depth + 1, VectorIndex, Index);
8915 if (NarrowBitWidth % 8 != 0)
8916 return std::nullopt;
8917 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
8919 if (Index >= NarrowByteWidth)
8921 ? std::optional<SDByteProvider>(
8929 Depth + 1, VectorIndex, StartingIndex);
8931 auto OffsetOp = dyn_cast<ConstantSDNode>(
Op->getOperand(1));
8933 return std::nullopt;
8935 VectorIndex = OffsetOp->getZExtValue();
8939 if (NarrowBitWidth % 8 != 0)
8940 return std::nullopt;
8941 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
8944 if (Index >= NarrowByteWidth)
8945 return std::nullopt;
8953 if (*VectorIndex * NarrowByteWidth > StartingIndex)
8954 return std::nullopt;
8955 if ((*VectorIndex + 1) * NarrowByteWidth <= StartingIndex)
8956 return std::nullopt;
8959 VectorIndex, StartingIndex);
8962 auto L = cast<LoadSDNode>(
Op.getNode());
8963 if (!L->isSimple() || L->isIndexed())
8964 return std::nullopt;
8966 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
8967 if (NarrowBitWidth % 8 != 0)
8968 return std::nullopt;
8969 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
8974 if (Index >= NarrowByteWidth)
8976 ? std::optional<SDByteProvider>(
8980 unsigned BPVectorIndex = VectorIndex.value_or(0U);
8985 return std::nullopt;
9000 int64_t FirstOffset) {
9002 unsigned Width = ByteOffsets.
size();
9004 return std::nullopt;
9006 bool BigEndian =
true, LittleEndian =
true;
9007 for (
unsigned i = 0; i < Width; i++) {
9008 int64_t CurrentByteOffset = ByteOffsets[i] - FirstOffset;
9011 if (!BigEndian && !LittleEndian)
9012 return std::nullopt;
9015 assert((BigEndian != LittleEndian) &&
"It should be either big endian or"
9022 switch (
Value.getOpcode()) {
9027 return Value.getOperand(0);
9065 EVT MemVT =
N->getMemoryVT();
9066 if (!(MemVT == MVT::i8 || MemVT == MVT::i16 || MemVT == MVT::i32) ||
9067 !
N->isSimple() ||
N->isIndexed())
9074 unsigned MaxWideNumBits = 64;
9075 unsigned MaxStores = MaxWideNumBits / NarrowNumBits;
9076 while (
auto *Store = dyn_cast<StoreSDNode>(Chain)) {
9084 if (
Store->getMemoryVT() != MemVT || !
Store->isSimple() ||
9088 Chain =
Store->getChain();
9089 if (MaxStores < Stores.
size())
9093 if (Stores.
size() < 2)
9098 unsigned NumStores = Stores.
size();
9099 unsigned WideNumBits = NumStores * NarrowNumBits;
9101 if (WideVT != MVT::i16 && WideVT != MVT::i32 && WideVT != MVT::i64)
9110 std::optional<BaseIndexOffset>
Base;
9111 for (
auto *Store : Stores) {
9122 isa<ConstantSDNode>(WideVal.
getOperand(1))) {
9130 if (ShiftAmtC % NarrowNumBits != 0)
9137 Offset = ShiftAmtC / NarrowNumBits;
9143 SourceValue = WideVal;
9144 else if (SourceValue != WideVal) {
9152 SourceValue = WideVal;
9161 int64_t ByteOffsetFromBase = 0;
9164 else if (!
Base->equalBaseIndex(
Ptr, DAG, ByteOffsetFromBase))
9168 if (ByteOffsetFromBase < FirstOffset) {
9170 FirstOffset = ByteOffsetFromBase;
9174 if (Offset < 0 || Offset >= NumStores || OffsetMap[
Offset] !=
INT64_MAX)
9176 OffsetMap[
Offset] = ByteOffsetFromBase;
9180 assert(FirstStore &&
"First store must be set");
9187 if (!Allowed || !
Fast)
9192 auto checkOffsets = [&](
bool MatchLittleEndian) {
9193 if (MatchLittleEndian) {
9194 for (
unsigned i = 0; i != NumStores; ++i)
9195 if (OffsetMap[i] != i * (NarrowNumBits / 8) + FirstOffset)
9198 for (
unsigned i = 0, j = NumStores - 1; i != NumStores; ++i, --
j)
9199 if (OffsetMap[j] != i * (NarrowNumBits / 8) + FirstOffset)
9206 bool NeedBswap =
false;
9207 bool NeedRotate =
false;
9210 if (NarrowNumBits == 8 && checkOffsets(Layout.
isBigEndian()))
9212 else if (NumStores == 2 && checkOffsets(Layout.
isBigEndian()))
9221 "Unexpected store value to merge");
9230 }
else if (NeedRotate) {
9231 assert(WideNumBits % 2 == 0 &&
"Unexpected type for rotate");
9277 "Can only match load combining against OR nodes");
9280 EVT VT =
N->getValueType(0);
9281 if (VT != MVT::i16 && VT != MVT::i32 && VT != MVT::i64)
9287 assert(
P.hasSrc() &&
"Must be a memory byte provider");
9288 auto *
Load = cast<LoadSDNode>(
P.Src.value());
9290 unsigned LoadBitWidth =
Load->getMemoryVT().getScalarSizeInBits();
9292 assert(LoadBitWidth % 8 == 0 &&
9293 "can only analyze providers for individual bytes not bit");
9294 unsigned LoadByteWidth = LoadBitWidth / 8;
9299 std::optional<BaseIndexOffset>
Base;
9303 std::optional<SDByteProvider> FirstByteProvider;
9309 unsigned ZeroExtendedBytes = 0;
9310 for (
int i = ByteWidth - 1; i >= 0; --i) {
9317 if (
P->isConstantZero()) {
9320 if (++ZeroExtendedBytes != (ByteWidth -
static_cast<unsigned>(i)))
9324 assert(
P->hasSrc() &&
"provenance should either be memory or zero");
9325 auto *
L = cast<LoadSDNode>(
P->Src.value());
9331 else if (Chain != LChain)
9336 int64_t ByteOffsetFromBase = 0;
9345 if (
L->getMemoryVT().isVector()) {
9346 unsigned LoadWidthInBit =
L->getMemoryVT().getScalarSizeInBits();
9347 if (LoadWidthInBit % 8 != 0)
9349 unsigned ByteOffsetFromVector =
P->SrcOffset * LoadWidthInBit / 8;
9350 Ptr.addToOffset(ByteOffsetFromVector);
9356 else if (!
Base->equalBaseIndex(
Ptr, DAG, ByteOffsetFromBase))
9360 ByteOffsetFromBase += MemoryByteOffset(*
P);
9361 ByteOffsets[i] = ByteOffsetFromBase;
9364 if (ByteOffsetFromBase < FirstOffset) {
9365 FirstByteProvider =
P;
9366 FirstOffset = ByteOffsetFromBase;
9372 assert(!Loads.
empty() &&
"All the bytes of the value must be loaded from "
9373 "memory, so there must be at least one load which produces the value");
9374 assert(
Base &&
"Base address of the accessed memory location must be set");
9377 bool NeedsZext = ZeroExtendedBytes > 0;
9388 if (LegalOperations &&
9396 ArrayRef(ByteOffsets).drop_back(ZeroExtendedBytes), FirstOffset);
9400 assert(FirstByteProvider &&
"must be set");
9404 if (MemoryByteOffset(*FirstByteProvider) != 0)
9406 auto *FirstLoad = cast<LoadSDNode>(FirstByteProvider->Src.value());
9413 bool NeedsBswap = IsBigEndianTarget != *IsBigEndian;
9420 if (NeedsBswap && (LegalOperations || NeedsZext) &&
9426 if (NeedsBswap && NeedsZext && LegalOperations &&
9434 *FirstLoad->getMemOperand(), &
Fast);
9435 if (!Allowed || !
Fast)
9440 Chain, FirstLoad->getBasePtr(),
9441 FirstLoad->getPointerInfo(), MemVT, FirstLoad->getAlign());
9481 EVT VT =
N->getValueType(0);
9503 M =
And.getOperand(XorIdx ? 0 : 1);
9509 if (!matchAndXor(N0, 0, N1) && !matchAndXor(N0, 1, N1) &&
9510 !matchAndXor(N1, 0, N0) && !matchAndXor(N1, 1, N0))
9516 if (isa<ConstantSDNode>(
M.getNode()))
9584 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
9596 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
9617 if (
SDValue Combined = visitADDLike(
N))
9624 isSetCCEquivalent(N0, LHS, RHS,
CC,
true)) {
9626 LHS.getValueType());
9627 if (!LegalOperations ||
9645 CombineTo(
N, SetCC);
9647 recursivelyDeleteUnusedNodes(N0.
getNode());
9663 AddToWorklist(
V.getNode());
9672 if (isOneUseSetCC(N01) || isOneUseSetCC(N00)) {
9677 return DAG.
getNode(NewOpcode,
DL, VT, N00, N01);
9685 if (isa<ConstantSDNode>(N01) || isa<ConstantSDNode>(N00)) {
9690 return DAG.
getNode(NewOpcode,
DL, VT, N00, N01);
9713 AddToWorklist(NotX.
getNode());
9718 if (!LegalOperations || hasOperation(
ISD::ABS, VT)) {
9722 SDValue A0 =
A.getOperand(0), A1 =
A.getOperand(1);
9724 if ((A0 == S && A1 == S0) || (A1 == S && A0 == S0))
9761 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
9772 if (
SDValue MM = unfoldMaskedMerge(
N))
9795 unsigned LogicOpcode = LogicOp.
getOpcode();
9801 unsigned ShiftOpcode = Shift->
getOpcode();
9804 assert(C1Node &&
"Expected a shift with constant operand");
9807 const APInt *&ShiftAmtVal) {
9808 if (V.getOpcode() != ShiftOpcode || !V.hasOneUse())
9816 ShiftOp = V.getOperand(0);
9821 if (ShiftAmtVal->getBitWidth() != C1Val.
getBitWidth())
9826 bool Overflow =
false;
9827 APInt NewShiftAmt = C1Val.
uadd_ov(*ShiftAmtVal, Overflow);
9832 if (NewShiftAmt.
uge(V.getScalarValueSizeInBits()))
9841 if (matchFirstShift(LogicOp.
getOperand(0),
X, C0Val))
9843 else if (matchFirstShift(LogicOp.
getOperand(1),
X, C0Val))
9855 return DAG.
getNode(LogicOpcode,
DL, VT, NewShift1, NewShift2,
9885 switch (
LHS.getOpcode()) {
9905 isa<ConstantSDNode>(BinOpLHSVal.
getOperand(1));
9909 if (!IsShiftByConstant && !IsCopyOrSelect)
9912 if (IsCopyOrSelect &&
N->hasOneUse())
9917 EVT VT =
N->getValueType(0);
9919 N->getOpcode(),
DL, VT, {LHS.getOperand(1), N->getOperand(1)})) {
9922 return DAG.
getNode(
LHS.getOpcode(),
DL, VT, NewShift, NewRHS);
9933 EVT TruncVT =
N->getValueType(0);
9934 if (
N->hasOneUse() &&
N->getOperand(0).hasOneUse() &&
9936 SDValue N01 =
N->getOperand(0).getOperand(1);
9939 SDValue N00 =
N->getOperand(0).getOperand(0);
9942 AddToWorklist(Trunc00.
getNode());
9943 AddToWorklist(Trunc01.
getNode());
9955 EVT VT =
N->getValueType(0);
9970 bool OutOfRange =
false;
9972 OutOfRange |=
C->getAPIntValue().uge(Bitsize);
9980 return DAG.
getNode(
N->getOpcode(), dl, VT, N0, Amt);
9985 if (RotAmtC && RotAmtC->getAPIntValue() == 8 &&
9997 return DAG.
getNode(
N->getOpcode(), dl, VT, N0, NewOp1);
10009 bool SameSide = (
N->getOpcode() == NextOp);
10016 if (Norm1 && Norm2)
10018 CombineOp, dl, ShiftVT, {Norm1, Norm2})) {
10020 {CombinedShift, BitsizeC});
10022 ISD::UREM, dl, ShiftVT, {CombinedShift, BitsizeC});
10024 CombinedShiftNorm);
10048 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10071 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10081 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10092 return (c1 + c2).uge(OpSizeInBits);
10102 return (c1 + c2).ult(OpSizeInBits);
10129 return c2.
uge(OpSizeInBits - InnerBitwidth) &&
10130 (c1 + c2).uge(OpSizeInBits);
10142 return c2.
uge(OpSizeInBits - InnerBitwidth) &&
10143 (c1 + c2).ult(OpSizeInBits);
10167 return c1.
ult(VT.getScalarSizeInBits()) && (c1 == c2);
10175 AddToWorklist(NewSHL.
getNode());
10183 const APInt &LHSC =
LHS->getAPIntValue();
10184 const APInt &RHSC =
RHS->getAPIntValue();
10185 return LHSC.
ult(OpSizeInBits) && RHSC.
ult(OpSizeInBits) &&
10257 AddToWorklist(Shl0.
getNode());
10276 {Add.getOperand(1)})) {
10296 if (
SDValue NewSHL = visitShiftByConstant(
N))
10330 APInt NewStep = C0 << ShlVal;
10345 "SRL or SRA node is required here!");
10354 SDValue ShiftOperand =
N->getOperand(0);
10365 if (!IsSignExt && !IsZeroExt)
10372 auto UserOfLowerBits = [NarrowVTSize](
SDNode *U) {
10377 if (!UShiftAmtSrc) {
10381 return UShiftAmt < NarrowVTSize;
10395 unsigned ActiveBits = IsSignExt
10396 ?
Constant->getAPIntValue().getSignificantBits()
10397 :
Constant->getAPIntValue().getActiveBits();
10398 if (ActiveBits > NarrowVTSize)
10415 "Cannot have a multiply node with two different operand types.");
10426 if (ShiftAmt != NarrowVTSize)
10448 bool IsSigned =
N->getOpcode() ==
ISD::SRA;
10455 unsigned Opcode =
N->getOpcode();
10460 EVT VT =
N->getValueType(0);
10510 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10513 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10529 APInt Sum = c1 + c2;
10530 unsigned ShiftSum =
10541 "Expected matchBinaryPredicate to return one element for "
10545 ShiftValue = ShiftValues[0];
10573 if ((ShiftAmt > 0) &&
10583 N->getValueType(0), Trunc);
10618 DAG.
getConstant(AddC->getAPIntValue().lshr(ShiftAmt).trunc(
10635 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10652 if (LargeShift->getAPIntValue() == TruncBits) {
10673 if (
SDValue NewSRA = visitShiftByConstant(
N))
10682 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
10685 if (
SDValue AVG = foldShiftToAvg(
N))
10708 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10711 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10727 return (c1 + c2).uge(OpSizeInBits);
10737 return (c1 + c2).ult(OpSizeInBits);
10757 if (c1 + OpSizeInBits == InnerShiftSize) {
10758 if (c1 + c2 >= InnerShiftSize)
10768 c1 + c2 < InnerShiftSize) {
10773 OpSizeInBits - c2),
10788 const APInt &LHSC =
LHS->getAPIntValue();
10789 const APInt &RHSC =
RHS->getAPIntValue();
10790 return LHSC.
ult(OpSizeInBits) && RHSC.
ult(OpSizeInBits) &&
10831 AddToWorklist(SmallShift.
getNode());
10859 APInt UnknownBits = ~Known.Zero;
10875 AddToWorklist(
Op.getNode());
10884 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10894 if (
SDValue NewSRL = visitShiftByConstant(
N))
10898 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
10925 if (
N->hasOneUse()) {
10934 AddToWorklist(
User);
10942 if (
SDValue AVG = foldShiftToAvg(
N))
10949 EVT VT =
N->getValueType(0);
10962 return IsFSHL ? N0 : N1;
10964 auto IsUndefOrZero = [](
SDValue V) {
10975 return DAG.
getNode(
N->getOpcode(),
DL, VT, N0, N1,
10981 return IsFSHL ? N0 : N1;
10987 if (IsUndefOrZero(N0))
10991 if (IsUndefOrZero(N1))
11003 auto *
LHS = dyn_cast<LoadSDNode>(N0);
11004 auto *
RHS = dyn_cast<LoadSDNode>(N1);
11005 if (LHS && RHS &&
LHS->isSimple() &&
RHS->isSimple() &&
11006 LHS->getAddressSpace() ==
RHS->getAddressSpace() &&
11016 RHS->getAddressSpace(), NewAlign,
11017 RHS->getMemOperand()->getFlags(), &
Fast) &&
11021 AddToWorklist(NewPtr.
getNode());
11023 VT,
DL,
RHS->getChain(), NewPtr,
11024 RHS->getPointerInfo().getWithOffset(PtrOff), NewAlign,
11025 RHS->getMemOperand()->getFlags(),
RHS->getAAInfo());
11027 WorklistRemover DeadNodes(*
this);
11054 if (N0 == N1 && hasOperation(RotOpc, VT))
11055 return DAG.
getNode(RotOpc,
DL, VT, N0, N2);
11100 EVT SrcVT =
N->getValueType(0);
11103 N =
N->getOperand(0).getNode();
11108 EVT VT =
N->getValueType(0);
11109 SDValue AbsOp1 =
N->getOperand(0);
11137 VT0 = cast<VTSDNode>(Op0.
getOperand(1))->getVT();
11138 VT1 = cast<VTSDNode>(Op1.
getOperand(1))->getVT();
11147 EVT MaxVT = VT0.
bitsGT(VT1) ? VT0 : VT1;
11148 if ((VT0 == MaxVT || Op0->
hasOneUse()) &&
11150 (!LegalTypes || hasOperation(ABDOpcode, MaxVT))) {
11160 if (!LegalOperations || hasOperation(ABDOpcode, VT)) {
11170 EVT VT =
N->getValueType(0);
11205 EVT VT =
N->getValueType(0);
11228 auto *ShAmt = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
11230 if (ShAmt && ShAmt->getAPIntValue().ult(BW) &&
11231 ShAmt->getZExtValue() >= (BW / 2) &&
11232 (ShAmt->getZExtValue() % 16) == 0 && TLI.
isTypeLegal(HalfVT) &&
11234 (!LegalOperations || hasOperation(
ISD::BSWAP, HalfVT))) {
11236 if (
uint64_t NewShAmt = (ShAmt->getZExtValue() - (BW / 2)))
11251 auto *ShAmt = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
11252 if (ShAmt && ShAmt->getAPIntValue().ult(BW) &&
11253 ShAmt->getZExtValue() % 8 == 0) {
11268 EVT VT =
N->getValueType(0);
11296 EVT VT =
N->getValueType(0);
11313 EVT VT =
N->getValueType(0);
11325 EVT VT =
N->getValueType(0);
11342 EVT VT =
N->getValueType(0);
11354 EVT VT =
N->getValueType(0);
11366 const APInt &Amt = AmtC->getAPIntValue();
11367 if (Amt.
ult(NumBits)) {
11401 EVT VT =
LHS.getValueType();
11407 return (Flags.hasNoSignedZeros() ||
Options.NoSignedZerosFPMath) &&
11409 (Flags.hasNoNaNs() ||
11459 const unsigned Opcode =
N->getOpcode();
11465 unsigned FloorISD = 0;
11466 auto VT =
N->getValueType(0);
11467 bool IsUnsigned =
false;
11496 if (IsUnsigned && !
Add->getFlags().hasNoUnsignedWrap())
11499 if (!IsUnsigned && !
Add->getFlags().hasNoSignedWrap())
11502 return DAG.
getNode(FloorISD,
SDLoc(
N),
N->getValueType(0), {A, B});
11509 if ((LHS == True && RHS == False) || (LHS == False && RHS == True))
11515 True, DAG, LegalOperations, ForCodeSize);
11527 if (LHS == NegTrue) {
11531 RHS, DAG, LegalOperations, ForCodeSize);
11534 if (NegRHS == False) {
11536 False,
CC, TLI, DAG);
11556 EVT VT =
N->getValueType(0);
11558 VT !=
Cond.getOperand(0).getValueType())
11605 EVT VT =
N->getValueType(0);
11606 EVT CondVT =
Cond.getValueType();
11612 auto *C1 = dyn_cast<ConstantSDNode>(N1);
11613 auto *C2 = dyn_cast<ConstantSDNode>(N2);
11617 if (CondVT != MVT::i1 || LegalOperations) {
11632 C1->
isZero() && C2->isOne()) {
11647 assert(CondVT == MVT::i1 && !LegalOperations);
11650 if (C1->
isOne() && C2->isZero())
11658 if (C1->
isZero() && C2->isOne()) {
11665 if (C1->
isZero() && C2->isAllOnes()) {
11678 const APInt &C1Val = C1->getAPIntValue();
11679 const APInt &C2Val = C2->getAPIntValue();
11682 if (C1Val - 1 == C2Val) {
11688 if (C1Val + 1 == C2Val) {
11708 if (C2->isAllOnes()) {
11720template <
class MatchContextClass>
11724 N->getOpcode() == ISD::VP_SELECT) &&
11725 "Expected a (v)(vp.)select");
11727 SDValue T =
N->getOperand(1),
F =
N->getOperand(2);
11728 EVT VT =
N->getValueType(0);
11730 MatchContextClass matcher(DAG, TLI,
N);
11766 EVT VT =
N->getValueType(0);
11830 EVT VT =
LHS.getValueType();
11832 if (LegalOperations && !hasOperation(ABDOpc, VT))
11842 return DAG.
getNode(ABDOpc,
DL, VT, LHS, RHS);
11845 hasOperation(ABDOpc, VT))
11854 return DAG.
getNode(ABDOpc,
DL, VT, LHS, RHS);
11857 hasOperation(ABDOpc, VT))
11871 EVT VT =
N->getValueType(0);
11879 if (
SDValue V = foldBoolSelectToLogic<EmptyMatchContext>(
N,
DL, DAG))
11889 if (
SDValue V = foldSelectOfConstants(
N))
11893 if (SimplifySelectOps(
N, N1, N2))
11896 if (VT0 == MVT::i1) {
11905 bool normalizeToSequence =
11914 if (normalizeToSequence || !InnerSelect.
use_empty())
11916 InnerSelect, N2, Flags);
11919 recursivelyDeleteUnusedNodes(InnerSelect.
getNode());
11926 Cond1, N1, N2, Flags);
11927 if (normalizeToSequence || !InnerSelect.
use_empty())
11929 InnerSelect, Flags);
11932 recursivelyDeleteUnusedNodes(InnerSelect.
getNode());
11942 if (!normalizeToSequence) {
11948 if (
SDValue Combined = visitANDLike(N0, N1_0,
N)) {
11961 if (!normalizeToSequence) {
11967 if (
SDValue Combined = visitORLike(N0, N2_0,
DL))
12003 combineMinNumMaxNum(
DL, VT, Cond0, Cond1, N1, N2,
CC))
12014 auto *
C = dyn_cast<ConstantSDNode>(N2.
getOperand(1));
12015 auto *NotC = dyn_cast<ConstantSDNode>(Cond1);
12016 if (
C && NotC &&
C->getAPIntValue() == ~NotC->getAPIntValue()) {
12036 (!LegalOperations &&
12047 if (
SDValue ABD = foldSelectToABD(Cond0, Cond1, N1, N2,
CC,
DL))
12050 if (
SDValue NewSel = SimplifySelect(
DL, N0, N1, N2))
12055 if (
SDValue BinOp = foldSelectOfBinops(
N))
12071 EVT VT =
N->getValueType(0);
12079 if (
LHS->getNumOperands() != 2 ||
RHS->getNumOperands() != 2)
12088 for (
int i = 0; i < NumElems / 2; ++i) {
12089 if (
Cond->getOperand(i)->isUndef())
12092 if (BottomHalf ==
nullptr)
12093 BottomHalf = cast<ConstantSDNode>(
Cond.getOperand(i));
12094 else if (
Cond->getOperand(i).getNode() != BottomHalf)
12100 for (
int i = NumElems / 2; i < NumElems; ++i) {
12101 if (
Cond->getOperand(i)->isUndef())
12104 if (TopHalf ==
nullptr)
12105 TopHalf = cast<ConstantSDNode>(
Cond.getOperand(i));
12106 else if (
Cond->getOperand(i).getNode() != TopHalf)
12110 assert(TopHalf && BottomHalf &&
12111 "One half of the selector was all UNDEFs and the other was all the "
12112 "same value. This should have been addressed before this function.");
12115 BottomHalf->
isZero() ?
RHS->getOperand(0) :
LHS->getOperand(0),
12116 TopHalf->
isZero() ?
RHS->getOperand(1) :
LHS->getOperand(1));
12129 EVT VT = BasePtr.getValueType();
12133 SplatVal.getValueType() == VT) {
12139 if (Index.getOpcode() !=
ISD::ADD)
12145 Index = Index.getOperand(1);
12151 Index = Index.getOperand(0);
12166 Index = Index.getOperand(0);
12179 Index = Index.getOperand(0);
12264 MST1->isSimple() && MST1->getBasePtr() ==
Ptr &&
12267 MST1->getMemoryVT().getStoreSize()) ||
12271 CombineTo(MST1, MST1->getChain());
12288 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
12292 Value.getValueType().isInteger() &&
12293 (!isa<ConstantSDNode>(
Value) ||
12294 !cast<ConstantSDNode>(
Value)->isOpaque())) {
12295 APInt TruncDemandedBits =
12321 Value.getOperand(0).getValueType());
12332 auto *SST = cast<VPStridedStoreSDNode>(
N);
12335 if (
auto *CStride = dyn_cast<ConstantSDNode>(SST->getStride());
12336 CStride && CStride->getZExtValue() == EltVT.
getStoreSize()) {
12338 SST->getBasePtr(), SST->getOffset(), SST->getMask(),
12339 SST->getVectorLength(), SST->getMemoryVT(),
12340 SST->getMemOperand(), SST->getAddressingMode(),
12341 SST->isTruncatingStore(), SST->isCompressingStore());
12350 SDValue Passthru =
N->getOperand(2);
12353 bool HasPassthru = !Passthru.
isUndef();
12366 unsigned NumSelected = 0;
12368 for (
unsigned I = 0;
I < NumElmts; ++
I) {
12381 for (
unsigned Rest = NumSelected; Rest < NumElmts; ++Rest) {
12436 return CombineTo(
N, PassThru, MGT->
getChain());
12472 return CombineTo(
N, NewLd, NewLd.
getValue(1));
12476 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
12504 EVT DataVT =
Index.getValueType();
12512 auto *SLD = cast<VPStridedLoadSDNode>(
N);
12515 if (
auto *CStride = dyn_cast<ConstantSDNode>(SLD->getStride());
12516 CStride && CStride->getZExtValue() == EltVT.
getStoreSize()) {
12518 SLD->getAddressingMode(), SLD->getExtensionType(), SLD->getValueType(0),
12519 SDLoc(
N), SLD->getChain(), SLD->getBasePtr(), SLD->getOffset(),
12520 SLD->getMask(), SLD->getVectorLength(), SLD->getMemoryVT(),
12521 SLD->getMemOperand(), SLD->isExpandingLoad());
12522 return CombineTo(
N, NewLd, NewLd.
getValue(1));
12533 EVT VT =
N->getValueType(0);
12534 if (!
Cond.hasOneUse() ||
Cond.getScalarValueSizeInBits() != 1 ||
12543 bool AllAddOne =
true;
12544 bool AllSubOne =
true;
12546 for (
unsigned i = 0; i != Elts; ++i) {
12568 if (AllAddOne || AllSubOne) {
12604 if (
SDValue V = foldBoolSelectToLogic<VPMatchContext>(
N,
DL, DAG))
12614 EVT VT =
N->getValueType(0);
12620 if (
SDValue V = foldBoolSelectToLogic<EmptyMatchContext>(
N,
DL, DAG))
12646 bool isAbs =
false;
12665 AddToWorklist(Shift.
getNode());
12666 AddToWorklist(
Add.getNode());
12678 if (
SDValue FMinMax = combineMinNumMaxNum(
DL, VT, LHS, RHS, N1, N2,
CC))
12693 EVT NarrowVT =
LHS.getValueType();
12701 SetCCWidth != 1 && SetCCWidth < WideWidth &&
12717 if (
SDValue ABD = foldSelectToABD(LHS, RHS, N1, N2,
CC,
DL))
12747 (OpLHS == CondLHS || OpRHS == CondLHS))
12750 if (OpRHS.getOpcode() == CondRHS.getOpcode() &&
12753 CondLHS == OpLHS) {
12758 return Cond->getAPIntValue() ==
~Op->getAPIntValue();
12799 if (OpLHS == LHS) {
12815 return (!
Op && !
Cond) ||
12817 Cond->getAPIntValue() == (-
Op->getAPIntValue() - 1));
12848 if (SimplifySelectOps(
N, N1, N2))
12868 if (
SDValue V = foldVSelectOfConstants(
N))
12902 AddToWorklist(
SCC.getNode());
12906 if (
auto *SCCC = dyn_cast<ConstantSDNode>(
SCC.getNode()))
12907 return SCCC->isZero() ? N3 : N2;
12911 if (
SCC->isUndef())
12918 SCC.getOperand(1), N2, N3,
SCC.getOperand(2));
12925 if (SimplifySelectOps(
N, N2, N3))
12929 return SimplifySelectCC(
DL, N0, N1, N2, N3,
CC);
12937 N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BRCOND;
12940 EVT VT =
N->getValueType(0);
12941 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
12947 if (PreferSetCC && Combined.getOpcode() !=
ISD::SETCC) {
12948 SDValue NewSetCC = rebuildSetCC(Combined);
12976 A.getOperand(0) ==
B.getOperand(0);
12980 B.getOperand(0) ==
A;
12983 bool IsRotate =
false;
12986 if (IsAndWithShift(N0, N1)) {
12988 ShiftOrRotate = N1;
12989 }
else if (IsAndWithShift(N1, N0)) {
12991 ShiftOrRotate = N0;
12992 }
else if (IsRotateWithOp(N0, N1)) {
12995 ShiftOrRotate = N1;
12996 }
else if (IsRotateWithOp(N1, N0)) {
12999 ShiftOrRotate = N0;
13002 if (AndOrOp && ShiftOrRotate && ShiftOrRotate.hasOneUse() &&
13007 auto GetAPIntValue = [](
SDValue Op) -> std::optional<APInt> {
13010 if (CNode ==
nullptr)
13011 return std::nullopt;
13014 std::optional<APInt> AndCMask =
13015 IsRotate ? std::nullopt : GetAPIntValue(AndOrOp.
getOperand(1));
13016 std::optional<APInt> ShiftCAmt =
13017 GetAPIntValue(ShiftOrRotate.getOperand(1));
13021 if (ShiftCAmt && (IsRotate || AndCMask) && ShiftCAmt->ult(NumBits)) {
13022 unsigned ShiftOpc = ShiftOrRotate.getOpcode();
13024 bool CanTransform = IsRotate;
13025 if (!CanTransform) {
13027 CanTransform = *ShiftCAmt == (~*AndCMask).
popcount();
13029 CanTransform &= (*ShiftCAmt + AndCMask->popcount()) == NumBits;
13037 OpVT, ShiftOpc, ShiftCAmt->isPowerOf2(), *ShiftCAmt, AndCMask);
13039 if (CanTransform && NewShiftOpc != ShiftOpc) {
13041 DAG.
getNode(NewShiftOpc,
DL, OpVT, ShiftOrRotate.getOperand(0),
13042 ShiftOrRotate.getOperand(1));
13049 NumBits - ShiftCAmt->getZExtValue())
13050 :
APInt::getLowBitsSet(NumBits,
13051 NumBits - ShiftCAmt->getZExtValue());
13059 return DAG.
getSetCC(
DL, VT, NewAndOrOp, NewShiftOrRotate,
Cond);
13088 if (!
N.hasOneUse())
13091 if (!isa<LoadSDNode>(
N))
13117 unsigned Opcode =
N->getOpcode();
13119 EVT VT =
N->getValueType(0);
13122 "Expected EXTEND dag node in input!");
13163 unsigned Opcode =
N->getOpcode();
13165 EVT VT =
N->getValueType(0);
13168 "Expected EXTEND dag node in input!");
13173 if (isa<ConstantSDNode>(N0))
13174 return DAG.
getNode(Opcode,
DL, VT, N0);
13182 if (isa<ConstantSDNode>(Op1) && isa<ConstantSDNode>(Op2) &&
13193 unsigned FoldOpc = Opcode;
13216 for (
unsigned i = 0; i != NumElts; ++i) {
13218 if (
Op.isUndef()) {
13229 APInt C =
Op->getAsAPIntVal().zextOrTrunc(EVTBits);
13247 bool HasCopyToRegUses =
false;
13262 for (
unsigned i = 0; i != 2; ++i) {
13266 if (!isa<ConstantSDNode>(UseOp))
13280 HasCopyToRegUses =
true;
13283 if (HasCopyToRegUses) {
13284 bool BothLiveOut =
false;
13287 BothLiveOut =
true;
13294 return !ExtendNodes.
empty();
13304 for (
SDNode *SetCC : SetCCs) {
13307 for (
unsigned j = 0;
j != 2; ++
j) {
13309 if (SOp == OrigLoad)
13323 EVT DstVT =
N->getValueType(0);
13328 "Unexpected node type (not an extend)!");
13366 EVT SplitSrcVT = SrcVT;
13367 EVT SplitDstVT = DstVT;
13380 const unsigned NumSplits =
13387 for (
unsigned Idx = 0;
Idx < NumSplits;
Idx++) {
13406 AddToWorklist(NewChain.
getNode());
13408 CombineTo(
N, NewValue);
13414 ExtendSetCCUses(SetCCs, N0, NewValue, (
ISD::NodeType)
N->getOpcode());
13415 CombineTo(N0.
getNode(), Trunc, NewChain);
13423 EVT VT =
N->getValueType(0);
13424 EVT OrigVT =
N->getOperand(0).getValueType();
13446 EVT MemVT =
Load->getMemoryVT();
13467 Load->getChain(),
Load->getBasePtr(),
13468 Load->getMemoryVT(),
Load->getMemOperand());
13481 if (
SDValue(Load, 0).hasOneUse()) {
13485 Load->getValueType(0), ExtLoad);
13486 CombineTo(Load, Trunc, ExtLoad.
getValue(1));
13490 recursivelyDeleteUnusedNodes(N0.
getNode());
13499SDValue DAGCombiner::matchVSelectOpSizesWithSetCC(
SDNode *Cast) {
13500 unsigned CastOpcode = Cast->
getOpcode();
13504 "Unexpected opcode for vector select narrowing/widening");
13544 bool LegalOperations,
SDNode *
N,
13555 if ((LegalOperations || !LN0->
isSimple() ||
13566 Combiner.recursivelyDeleteUnusedNodes(LN0);
13579 bool NonNegZExt =
false) {
13586 "Unexpected load type or opcode");
13603 !cast<LoadSDNode>(N0)->isSimple()) &&
13607 bool DoXform =
true;
13620 Combiner.ExtendSetCCUses(SetCCs, N0, ExtLoad, ExtOpc);
13624 if (NoReplaceTrunc) {
13626 Combiner.recursivelyDeleteUnusedNodes(LN0);
13646 if ((LegalOperations || !cast<MaskedLoadSDNode>(N0)->
isSimple()) &&
13668 auto *ALoad = dyn_cast<AtomicSDNode>(N0);
13671 EVT MemoryVT = ALoad->getMemoryVT();
13680 EVT OrigVT = ALoad->getValueType(0);
13682 auto *NewALoad = cast<AtomicSDNode>(DAG.
getAtomic(
13684 ALoad->getBasePtr(), ALoad->getMemOperand()));
13685 NewALoad->setExtensionType(ExtLoadType);
13695 bool LegalOperations) {
13707 EVT VT =
N->getValueType(0);
13708 EVT XVT =
X.getValueType();
13724 return DAG.
getNode(ShiftOpcode,
DL, VT, NotX, ShiftAmount);
13738 EVT VT =
N->getValueType(0);
13748 if (VT.
isVector() && !LegalOperations &&
13767 if (SVT == MatchingVecType) {
13783 auto IsFreeToExtend = [&](
SDValue V) {
13791 cast<LoadSDNode>(V)->isSimple() &&
13805 if (
User->getOpcode() != ExtOpcode ||
User->getValueType(0) != VT)
13811 if (IsFreeToExtend(N00) && IsFreeToExtend(N01)) {
13831 SDValue ExtTrueVal = (SetCCWidth == 1)
13835 if (
SDValue SCC = SimplifySelectCC(
DL, N00, N01, ExtTrueVal, Zero,
CC,
true))
13847 return DAG.
getSelect(
DL, VT, SetCC, ExtTrueVal, Zero);
13856 EVT VT =
N->getValueType(0);
13860 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
13898 if (NarrowLoad.getNode() != N0.
getNode()) {
13899 CombineTo(N0.
getNode(), NarrowLoad);
13901 AddToWorklist(oye);
13909 unsigned OpBits =
Op.getScalarValueSizeInBits();
13915 if (OpBits == DestBits) {
13921 if (OpBits < DestBits) {
13930 Flags.setNoSignedWrap(
true);
13938 if (OpBits < DestBits)
13940 else if (OpBits > DestBits)
13960 if (
SDValue ExtLoad = CombineExtLoad(
N))
13995 bool NoReplaceTruncAnd = !N0.
hasOneUse();
13999 if (NoReplaceTruncAnd) {
14002 CombineTo(N0.
getNode(), TruncAnd);
14004 if (NoReplaceTrunc) {
14009 CombineTo(LN00, Trunc, ExtLoad.
getValue(1));
14028 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
14059 if (NewXor.getNode() == N0.
getNode()) {
14085 "Expected extend op");
14131 EVT VT =
N->getValueType(0);
14135 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
14166 APInt TruncatedBits =
14168 APInt(
Op.getScalarValueSizeInBits(), 0) :
14171 std::min(
Op.getScalarValueSizeInBits(),
14177 return ZExtOrTrunc;
14187 if (NarrowLoad.getNode() != N0.
getNode()) {
14188 CombineTo(N0.
getNode(), NarrowLoad);
14190 AddToWorklist(oye);
14198 if (
N->getFlags().hasNonNeg()) {
14206 if (OpBits == DestBits) {
14212 if (OpBits < DestBits) {
14222 Flags.setNoSignedWrap(
true);
14223 Flags.setNoUnsignedWrap(
true);
14235 AddToWorklist(
Op.getNode());
14239 return ZExtOrTrunc;
14245 AddToWorklist(
Op.getNode());
14281 if (
SDValue ExtLoad = CombineExtLoad(
N))
14301 bool DoXform =
true;
14305 auto *AndC = cast<ConstantSDNode>(N0.
getOperand(1));
14308 if (isAndLoadExtLoad(AndC, LN00, LoadResultTy, ExtVT))
14324 bool NoReplaceTruncAnd = !N0.
hasOneUse();
14328 if (NoReplaceTruncAnd) {
14331 CombineTo(N0.
getNode(), TruncAnd);
14333 if (NoReplaceTrunc) {
14338 CombineTo(LN00, Trunc, ExtLoad.
getValue(1));
14347 if (
SDValue ZExtLoad = CombineZExtLogicopShiftLoad(
N))
14363 if (!LegalOperations && VT.
isVector() &&
14395 if (
SDValue SCC = SimplifySelectCC(
14399 cast<CondCodeSDNode>(N0.
getOperand(2))->get(),
true))
14408 if (
auto *ShAmtC = dyn_cast<ConstantSDNode>(ShAmt)) {
14415 if (ShAmtC->getAPIntValue().ugt(KnownZeroBits)) {
14436 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
14460 EVT VT =
N->getValueType(0);
14494 if (NarrowLoad.getNode() != N0.
getNode()) {
14495 CombineTo(N0.
getNode(), NarrowLoad);
14497 AddToWorklist(oye);
14515 assert(isa<ConstantSDNode>(
Y) &&
"Expected constant to be folded!");
14531 bool DoXform =
true;
14544 CombineTo(
N, ExtLoad);
14545 if (NoReplaceTrunc) {
14547 recursivelyDeleteUnusedNodes(LN0);
14551 CombineTo(LN0, Trunc, ExtLoad.
getValue(1));
14565 if (!LegalOperations || TLI.
isLoadExtLegal(ExtType, VT, MemVT)) {
14569 CombineTo(
N, ExtLoad);
14571 recursivelyDeleteUnusedNodes(LN0);
14585 if (VT.
isVector() && !LegalOperations) {
14597 cast<CondCodeSDNode>(N0.
getOperand(2))->get());
14605 cast<CondCodeSDNode>(N0.
getOperand(2))->get());
14610 if (
SDValue SCC = SimplifySelectCC(
14613 cast<CondCodeSDNode>(N0.
getOperand(2))->get(),
true))
14627 unsigned Opcode =
N->getOpcode();
14630 EVT AssertVT = cast<VTSDNode>(N1)->getVT();
14634 AssertVT == cast<VTSDNode>(N0.
getOperand(1))->getVT())
14646 EVT BigA_AssertVT = cast<VTSDNode>(BigA.
getOperand(1))->getVT();
14647 EVT MinAssertVT = AssertVT.
bitsLT(BigA_AssertVT) ? AssertVT : BigA_AssertVT;
14661 EVT BigA_AssertVT = cast<VTSDNode>(BigA.
getOperand(1))->getVT();
14662 if (AssertVT.
bitsLT(BigA_AssertVT)) {
14676 Align AL = cast<AssertAlignSDNode>(
N)->getAlign();
14681 if (
auto *AAN = dyn_cast<AssertAlignSDNode>(N0))
14683 std::max(AL, AAN->getAlign()));
14693 unsigned AlignShift =
Log2(AL);
14698 if (LHSAlignShift >= AlignShift || RHSAlignShift >= AlignShift) {
14699 if (LHSAlignShift < AlignShift)
14701 if (RHSAlignShift < AlignShift)
14716 unsigned Opc =
N->getOpcode();
14720 EVT VT =
N->getValueType(0);
14730 unsigned ShAmt = 0;
14735 unsigned ShiftedOffset = 0;
14740 ExtVT = cast<VTSDNode>(
N->getOperand(1))->getVT();
14748 auto *LN = dyn_cast<LoadSDNode>(N0);
14749 auto *N1C = dyn_cast<ConstantSDNode>(
N->getOperand(1));
14755 uint64_t MemoryWidth = LN->getMemoryVT().getScalarSizeInBits();
14756 if (MemoryWidth <= ShAmt)
14767 LN->getExtensionType() != ExtType)
14771 auto AndC = dyn_cast<ConstantSDNode>(
N->getOperand(1));
14776 unsigned ActiveBits = 0;
14777 if (
Mask.isMask()) {
14778 ActiveBits =
Mask.countr_one();
14779 }
else if (
Mask.isShiftedMask(ShAmt, ActiveBits)) {
14780 ShiftedOffset = ShAmt;
14801 if (!
SRL.hasOneUse())
14806 auto *LN = dyn_cast<LoadSDNode>(
SRL.getOperand(0));
14807 auto *SRL1C = dyn_cast<ConstantSDNode>(
SRL.getOperand(1));
14814 ShAmt = SRL1C->getZExtValue();
14815 uint64_t MemoryWidth = LN->getMemoryVT().getSizeInBits();
14816 if (ShAmt >= MemoryWidth)
14843 isa<ConstantSDNode>(
Mask->getOperand(1))) {
14844 unsigned Offset, ActiveBits;
14845 const APInt& ShiftMask =
Mask->getConstantOperandAPInt(1);
14846 if (ShiftMask.
isMask()) {
14868 N0 =
SRL.getOperand(0);
14876 unsigned ShLeftAmt = 0;
14880 ShLeftAmt = N01->getZExtValue();
14886 if (!isa<LoadSDNode>(N0))
14893 !isLegalNarrowLdSt(LN0, ExtType, ExtVT, ShAmt))
14896 auto AdjustBigEndianShift = [&](
unsigned ShAmt) {
14897 unsigned LVTStoreBits =
14900 return LVTStoreBits - EVTStoreBits - ShAmt;
14905 unsigned PtrAdjustmentInBits =
14908 uint64_t PtrOff = PtrAdjustmentInBits / 8;
14914 AddToWorklist(NewPtr.
getNode());
14929 WorklistRemover DeadNodes(*
this);
14934 if (ShLeftAmt != 0) {
14946 if (ShiftedOffset != 0) {
14963 EVT VT =
N->getValueType(0);
14964 EVT ExtVT = cast<VTSDNode>(N1)->getVT();
14994 if ((N00Bits <= ExtVTBits ||
15010 if ((N00Bits == ExtVTBits ||
15011 (!IsZext && (N00Bits < ExtVTBits ||
15013 (!LegalOperations ||
15038 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
15045 if (
auto *ShAmt = dyn_cast<ConstantSDNode>(N0.
getOperand(1)))
15046 if (ShAmt->getAPIntValue().ule(VTBits - ExtVTBits)) {
15050 if (((VTBits - ExtVTBits) - ShAmt->getZExtValue()) < InSignBits)
15061 ExtVT == cast<LoadSDNode>(N0)->getMemoryVT() &&
15062 ((!LegalOperations && cast<LoadSDNode>(N0)->isSimple() &&
15065 auto *LN0 = cast<LoadSDNode>(N0);
15069 CombineTo(
N, ExtLoad);
15071 AddToWorklist(ExtLoad.
getNode());
15077 N0.
hasOneUse() && ExtVT == cast<LoadSDNode>(N0)->getMemoryVT() &&
15078 ((!LegalOperations && cast<LoadSDNode>(N0)->isSimple()) &&
15080 auto *LN0 = cast<LoadSDNode>(N0);
15084 CombineTo(
N, ExtLoad);
15092 if (ExtVT == Ld->getMemoryVT() && N0.
hasOneUse() &&
15096 VT,
DL, Ld->getChain(), Ld->getBasePtr(), Ld->getOffset(),
15097 Ld->getMask(), Ld->getPassThru(), ExtVT, Ld->getMemOperand(),
15098 Ld->getAddressingMode(),
ISD::SEXTLOAD, Ld->isExpandingLoad());
15099 CombineTo(
N, ExtMaskedLoad);
15106 if (
auto *GN0 = dyn_cast<MaskedGatherSDNode>(N0)) {
15107 if (
SDValue(GN0, 0).hasOneUse() && ExtVT == GN0->getMemoryVT() &&
15109 SDValue Ops[] = {GN0->getChain(), GN0->getPassThru(), GN0->getMask(),
15110 GN0->getBasePtr(), GN0->getIndex(), GN0->getScale()};
15113 DAG.
getVTList(VT, MVT::Other), ExtVT,
DL, Ops, GN0->getMemOperand(),
15116 CombineTo(
N, ExtLoad);
15118 AddToWorklist(ExtLoad.
getNode());
15141 (!LegalOperations ||
15155 bool LegalOperations) {
15156 unsigned InregOpcode =
N->getOpcode();
15160 EVT VT =
N->getValueType(0);
15162 Src.getValueType().getVectorElementType(),
15166 "Expected EXTEND_VECTOR_INREG dag node in input!");
15175 Src = Src.getOperand(0);
15176 if (Src.getValueType() != SrcVT)
15182 return DAG.
getNode(Opcode,
DL, VT, Src);
15187 EVT VT =
N->getValueType(0);
15212 EVT VT =
N->getValueType(0);
15233 unsigned NumSrcBits = In.getScalarValueSizeInBits();
15235 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
15256 unsigned NumSrcBits = In.getScalarValueSizeInBits();
15258 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
15279 unsigned NumSrcBits = In.getScalarValueSizeInBits();
15281 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
15304 auto AllowedTruncateSat = [&](
unsigned Opc,
EVT SrcVT,
EVT VT) ->
bool {
15316 }
else if (Src.getOpcode() ==
ISD::UMIN) {
15330 EVT VT =
N->getValueType(0);
15345 return SaturatedTR;
15372 EVT ExtVT = cast<VTSDNode>(ExtVal)->getVT();
15393 if (LegalTypes && !LegalOperations && VT.
isScalarInteger() && VT != MVT::i1 &&
15395 EVT TrTy =
N->getValueType(0);
15400 if (Src.getOpcode() ==
ISD::SRL && Src.getOperand(0)->hasOneUse()) {
15403 Src = Src.getOperand(0);
15410 EVT VecTy = Src.getOperand(0).getValueType();
15411 EVT ExTy = Src.getValueType();
15415 auto NewEltCnt = EltCnt * SizeRatio;
15420 SDValue EltNo = Src->getOperand(1);
15421 if (isa<ConstantSDNode>(EltNo) &&
isTypeLegal(NVT)) {
15423 int Index = isLE ? (Elt * SizeRatio + EltOffset)
15424 : (Elt * SizeRatio + (SizeRatio - 1) - EltOffset);
15435 if (!LegalOperations ||
15458 AddToWorklist(Amt.
getNode());
15507 if (BuildVectEltTy == TruncVecEltTy) {
15511 unsigned TruncEltOffset = BuildVecNumElts / TruncVecNumElts;
15512 unsigned FirstElt = isLE ? 0 : (TruncEltOffset - 1);
15514 assert((BuildVecNumElts % TruncVecNumElts) == 0 &&
15515 "Invalid number of elements");
15518 for (
unsigned i = FirstElt, e = BuildVecNumElts; i <
e;
15519 i += TruncEltOffset)
15529 if (
SDValue Reduced = reduceLoadWidth(
N))
15535 auto *LN0 = cast<LoadSDNode>(N0);
15552 unsigned NumDefs = 0;
15556 if (!
X.isUndef()) {
15567 X.getValueType().getVectorElementCount()));
15573 if (NumDefs == 1) {
15574 assert(
V.getNode() &&
"The single defined operand is empty!");
15576 for (
unsigned i = 0, e = VTs.
size(); i != e; ++i) {
15582 AddToWorklist(
NV.getNode());
15597 (!LegalOperations ||
15625 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
15639 if (!LegalOperations && N0.
hasOneUse() &&
15672 if (!LegalOperations && N0.
hasOneUse() &&
15708 !LD1->hasOneUse() || !LD2->hasOneUse() ||
15709 LD1->getAddressSpace() != LD2->getAddressSpace())
15712 unsigned LD1Fast = 0;
15713 EVT LD1VT = LD1->getValueType(0);
15718 *LD1->getMemOperand(), &LD1Fast) && LD1Fast)
15719 return DAG.
getLoad(VT,
SDLoc(
N), LD1->getChain(), LD1->getBasePtr(),
15720 LD1->getPointerInfo(), LD1->getAlign());
15735 EVT VT =
N->getValueType(0);
15772 auto IsBitCastOrFree = [&TLI, FPOpcode](
SDValue Op,
EVT VT) {
15786 IsBitCastOrFree(LogicOp0, VT)) {
15789 NumFPLogicOpsConv++;
15800 EVT VT =
N->getValueType(0);
15816 cast<BuildVectorSDNode>(N0)->isConstant())
15817 return ConstantFoldBITCASTofBUILD_VECTOR(N0.
getNode(),
15825 if (!LegalOperations ||
15831 if (
C.getNode() !=
N)
15844 auto IsFreeBitcast = [VT](
SDValue V) {
15846 V.getOperand(0).getValueType() == VT) ||
15867 ((!LegalOperations && cast<LoadSDNode>(N0)->isSimple()) ||
15881 if (
SDValue V = foldBitcastedFPLogic(
N, DAG, TLI))
15901 AddToWorklist(NewConv.
getNode());
15904 if (N0.
getValueType() == MVT::ppcf128 && !LegalTypes) {
15911 AddToWorklist(FlipBit.
getNode());
15918 AddToWorklist(
Hi.getNode());
15920 AddToWorklist(FlipBit.
getNode());
15924 AddToWorklist(FlipBits.
getNode());
15954 AddToWorklist(
X.getNode());
15958 if (OrigXWidth < VTWidth) {
15960 AddToWorklist(
X.getNode());
15961 }
else if (OrigXWidth > VTWidth) {
15966 X.getValueType(),
X,
15968 X.getValueType()));
15969 AddToWorklist(
X.getNode());
15971 AddToWorklist(
X.getNode());
15974 if (N0.
getValueType() == MVT::ppcf128 && !LegalTypes) {
15977 AddToWorklist(Cst.
getNode());
15979 AddToWorklist(
X.getNode());
15981 AddToWorklist(XorResult.
getNode());
15985 SDLoc(XorResult)));
15986 AddToWorklist(XorResult64.
getNode());
15990 AddToWorklist(FlipBit.
getNode());
15993 AddToWorklist(FlipBits.
getNode());
15999 AddToWorklist(
X.getNode());
16004 AddToWorklist(Cst.
getNode());
16012 if (
SDValue CombineLD = CombineConsecutiveLoads(N0.
getNode(), VT))
16035 auto PeekThroughBitcast = [&](
SDValue Op) {
16037 Op.getOperand(0).getValueType() == VT)
16056 for (
int i = 0; i != MaskScale; ++i)
16057 NewMask.
push_back(M < 0 ? -1 : M * MaskScale + i);
16062 return LegalShuffle;
16069 EVT VT =
N->getValueType(0);
16070 return CombineConsecutiveLoads(
N, VT);
16097 bool AllowMultipleMaybePoisonOperands =
16131 bool HadMaybePoisonOperands = !MaybePoisonOperands.
empty();
16132 bool IsNewMaybePoisonOperand = MaybePoisonOperands.
insert(
Op).second;
16133 if (IsNewMaybePoisonOperand)
16134 MaybePoisonOperandNumbers.
push_back(OpNo);
16135 if (!HadMaybePoisonOperands)
16137 if (IsNewMaybePoisonOperand && !AllowMultipleMaybePoisonOperands) {
16146 for (
unsigned OpNo : MaybePoisonOperandNumbers) {
16157 SDValue MaybePoisonOperand =
N->getOperand(0).getOperand(OpNo);
16166 FrozenMaybePoisonOperand.
getOperand(0) == FrozenMaybePoisonOperand) {
16170 MaybePoisonOperand);
16180 N0 =
N->getOperand(0);
16192 if (
auto *SVN = dyn_cast<ShuffleVectorSDNode>(N0)) {
16201 "Can't create node that may be undef/poison!");
16208ConstantFoldBITCASTofBUILD_VECTOR(
SDNode *BV,
EVT DstEltVT) {
16212 if (SrcEltVT == DstEltVT)
return SDValue(BV, 0);
16219 if (SrcBitSize == DstBitSize) {
16224 if (
Op.getValueType() != SrcEltVT)
16227 AddToWorklist(Ops.
back().getNode());
16241 BV = ConstantFoldBITCASTofBUILD_VECTOR(BV, IntVT).getNode();
16249 SDNode *Tmp = ConstantFoldBITCASTofBUILD_VECTOR(BV, TmpVT).getNode();
16252 return ConstantFoldBITCASTofBUILD_VECTOR(Tmp, DstEltVT);
16260 auto *BVN = cast<BuildVectorSDNode>(BV);
16266 if (!BVN->getConstantRawBits(IsLE, DstBitSize, RawBits, UndefElements))
16271 for (
unsigned I = 0, E = RawBits.
size();
I != E; ++
I) {
16272 if (UndefElements[
I])
16288 N->getFlags().hasAllowContract();
16293 return Options.NoInfsFPMath ||
N->getFlags().hasNoInfs();
16297template <
class MatchContextClass>
16301 EVT VT =
N->getValueType(0);
16303 MatchContextClass matcher(DAG, TLI,
N);
16306 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
16311 bool HasFMAD = !UseVP && (LegalOperations && TLI.
isFMADLegal(DAG,
N));
16315 (!LegalOperations || matcher.isOperationLegalOrCustom(
ISD::FMA, VT)) &&
16319 if (!HasFMAD && !HasFMA)
16323 Options.UnsafeFPMath || HasFMAD);
16325 if (!AllowFusionGlobally && !
N->getFlags().hasAllowContract())
16351 return AllowFusionGlobally ||
N->getFlags().hasAllowContract();
16362 return matcher.getNode(PreferredFusedOpcode, SL, VT, N0.
getOperand(0),
16369 return matcher.getNode(PreferredFusedOpcode, SL, VT, N1.
getOperand(0),
16381 bool CanReassociate =
16382 Options.UnsafeFPMath ||
N->getFlags().hasAllowReassociation();
16383 if (CanReassociate) {
16388 }
else if (isFusedOp(N1) && N1.
hasOneUse()) {
16394 while (E && isFusedOp(TmpFMA) && TmpFMA.
hasOneUse()) {
16419 PreferredFusedOpcode, SL, VT,
16433 PreferredFusedOpcode, SL, VT,
16445 return matcher.getNode(
16446 PreferredFusedOpcode, SL, VT,
X,
Y,
16447 matcher.getNode(PreferredFusedOpcode, SL, VT,
16451 if (isFusedOp(N0)) {
16472 return matcher.getNode(
16473 PreferredFusedOpcode, SL, VT,
16476 matcher.getNode(PreferredFusedOpcode, SL, VT,
16482 if (isFusedOp(N00)) {
16496 if (isFusedOp(N1)) {
16517 if (isFusedOp(N10)) {
16534template <
class MatchContextClass>
16538 EVT VT =
N->getValueType(0);
16540 MatchContextClass matcher(DAG, TLI,
N);
16543 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
16548 bool HasFMAD = !UseVP && (LegalOperations && TLI.
isFMADLegal(DAG,
N));
16552 (!LegalOperations || matcher.isOperationLegalOrCustom(
ISD::FMA, VT)) &&
16556 if (!HasFMAD && !HasFMA)
16561 Options.UnsafeFPMath || HasFMAD);
16564 if (!AllowFusionGlobally && !
N->getFlags().hasAllowContract())
16573 bool NoSignedZero =
Options.NoSignedZerosFPMath ||
Flags.hasNoSignedZeros();
16580 return AllowFusionGlobally ||
N->getFlags().hasAllowContract();
16586 return matcher.getNode(PreferredFusedOpcode, SL, VT, XY.
getOperand(0),
16597 return matcher.getNode(
16598 PreferredFusedOpcode, SL, VT,
16599 matcher.getNode(
ISD::FNEG, SL, VT, YZ.getOperand(0)),
16600 YZ.getOperand(1),
X);
16610 if (
SDValue V = tryToFoldXSubYZ(N0, N1))
16613 if (
SDValue V = tryToFoldXYSubZ(N0, N1))
16617 if (
SDValue V = tryToFoldXYSubZ(N0, N1))
16620 if (
SDValue V = tryToFoldXSubYZ(N0, N1))
16629 return matcher.
getNode(PreferredFusedOpcode, SL, VT,
16630 matcher.getNode(
ISD::FNEG, SL, VT, N00), N01,
16631 matcher.getNode(
ISD::FNEG, SL, VT, N1));
16644 PreferredFusedOpcode, SL, VT,
16647 matcher.getNode(
ISD::FNEG, SL, VT, N1));
16660 PreferredFusedOpcode, SL, VT,
16684 PreferredFusedOpcode, SL, VT,
16708 PreferredFusedOpcode, SL, VT,
16717 return Options.UnsafeFPMath ||
N->getFlags().hasAllowReassociation();
16731 bool CanFuse =
Options.UnsafeFPMath ||
N->getFlags().hasAllowContract();
16734 if (CanFuse && isFusedOp(N0) &&
16735 isContractableAndReassociableFMUL(N0.
getOperand(2)) &&
16737 return matcher.getNode(
16739 matcher.
getNode(PreferredFusedOpcode, SL, VT,
16747 if (CanFuse && isFusedOp(N1) &&
16748 isContractableAndReassociableFMUL(N1.
getOperand(2)) &&
16753 PreferredFusedOpcode, SL, VT,
16756 matcher.
getNode(PreferredFusedOpcode, SL, VT,
16757 matcher.getNode(
ISD::FNEG, SL, VT, N20), N21, N0));
16762 if (isFusedOp(N0) && N0->
hasOneUse()) {
16766 if (isContractableAndReassociableFMUL(N020) &&
16772 PreferredFusedOpcode, SL, VT,
16775 matcher.getNode(
ISD::FNEG, SL, VT, N1)));
16788 if (isFusedOp(N00)) {
16790 if (isContractableAndReassociableFMUL(N002) &&
16794 PreferredFusedOpcode, SL, VT,
16798 PreferredFusedOpcode, SL, VT,
16801 matcher.getNode(
ISD::FNEG, SL, VT, N1)));
16811 if (isContractableAndReassociableFMUL(N120) &&
16817 PreferredFusedOpcode, SL, VT,
16821 PreferredFusedOpcode, SL, VT,
16839 if (isContractableAndReassociableFMUL(N102) &&
16845 PreferredFusedOpcode, SL, VT,
16850 PreferredFusedOpcode, SL, VT,
16864SDValue DAGCombiner::visitFMULForFMADistributiveCombine(
SDNode *
N) {
16867 EVT VT =
N->getValueType(0);
16888 bool HasFMAD =
Options.UnsafeFPMath &&
16892 if (!HasFMAD && !HasFMA)
16904 if (
C->isExactlyValue(+1.0))
16905 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
16907 if (
C->isExactlyValue(-1.0))
16908 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
16915 if (
SDValue FMA = FuseFADD(N0, N1))
16917 if (
SDValue FMA = FuseFADD(N1, N0))
16927 if (C0->isExactlyValue(+1.0))
16928 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
16931 if (C0->isExactlyValue(-1.0))
16932 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
16937 if (C1->isExactlyValue(+1.0))
16938 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
16940 if (C1->isExactlyValue(-1.0))
16941 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
16948 if (
SDValue FMA = FuseFSUB(N0, N1))
16950 if (
SDValue FMA = FuseFSUB(N1, N0))
16960 if (
SDValue Fused = visitFADDForFMACombine<VPMatchContext>(
N)) {
16962 AddToWorklist(Fused.getNode());
16973 EVT VT =
N->getValueType(0);
16987 if (N0CFP && !N1CFP)
16992 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
16997 if (N1C && N1C->
isZero())
17001 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17007 N1, DAG, LegalOperations, ForCodeSize))
17013 N0, DAG, LegalOperations, ForCodeSize))
17020 return C &&
C->isExactlyValue(-2.0);
17024 if (isFMulNegTwo(N0)) {
17030 if (isFMulNegTwo(N1)) {
17041 if ((
Options.NoNaNsFPMath ||
Flags.hasNoNaNs()) && AllowNewConst) {
17055 (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros())) &&
17073 if (CFP01 && !CFP00 && N0.
getOperand(0) == N1) {
17094 if (CFP11 && !CFP10 && N1.
getOperand(0) == N0) {
17142 VT, N0, N1, Flags))
17147 if (
SDValue Fused = visitFADDForFMACombine<EmptyMatchContext>(
N)) {
17149 AddToWorklist(Fused.getNode());
17159 EVT VT =
N->getValueType(0);
17160 EVT ChainVT =
N->getValueType(1);
17167 N1, DAG, LegalOperations, ForCodeSize)) {
17169 {Chain, N0, NegN1});
17175 N0, DAG, LegalOperations, ForCodeSize)) {
17177 {Chain, N1, NegN0});
17187 EVT VT =
N->getValueType(0);
17202 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
17205 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17209 if (N1CFP && N1CFP->
isZero()) {
17211 Flags.hasNoSignedZeros()) {
17223 if (N0CFP && N0CFP->
isZero()) {
17225 (
Options.NoSignedZerosFPMath ||
Flags.hasNoSignedZeros())) {
17242 (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros())) &&
17258 if (
SDValue Fused = visitFSUBForFMACombine<EmptyMatchContext>(
N)) {
17259 AddToWorklist(Fused.getNode());
17282 EVT VT =
N->getValueType(0);
17285 std::optional<int> Mantissa;
17286 auto GetConstAndPow2Ops = [&](
unsigned ConstOpIdx) {
17287 if (ConstOpIdx == 1 &&
N->getOpcode() ==
ISD::FDIV)
17291 Pow2Op =
N->getOperand(1 - ConstOpIdx);
17304 if (CFP ==
nullptr)
17307 const APFloat &APF = CFP->getValueAPF();
17315 int CurExp =
ilogb(APF);
17318 N->getOpcode() ==
ISD::FMUL ? CurExp : (CurExp - MaxExpChange);
17321 N->getOpcode() ==
ISD::FDIV ? CurExp : (CurExp + MaxExpChange);
17329 Mantissa = ThisMantissa;
17331 return *Mantissa == ThisMantissa && ThisMantissa > 0;
17338 if (!GetConstAndPow2Ops(0) && !GetConstAndPow2Ops(1))
17367 NewIntVT, DAG.
getBitcast(NewIntVT, ConstOp), Shift);
17376 EVT VT =
N->getValueType(0);
17396 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
17399 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17402 if (
Options.UnsafeFPMath ||
Flags.hasAllowReassociation()) {
17428 VT, N0, N1, Flags))
17462 if (
Flags.hasNoNaNs() &&
Flags.hasNoSignedZeros() &&
17470 auto TrueOpnd = dyn_cast<ConstantFPSDNode>(
Select.getOperand(1));
17471 auto FalseOpnd = dyn_cast<ConstantFPSDNode>(
Select.getOperand(2));
17473 if (TrueOpnd && FalseOpnd &&
17475 isa<ConstantFPSDNode>(
Cond.getOperand(1)) &&
17476 cast<ConstantFPSDNode>(
Cond.getOperand(1))->isExactlyValue(0.0)) {
17494 if (TrueOpnd->isExactlyValue(-1.0) && FalseOpnd->isExactlyValue(1.0) &&
17498 if (TrueOpnd->isExactlyValue(1.0) && FalseOpnd->isExactlyValue(-1.0))
17507 if (
SDValue Fused = visitFMULForFMADistributiveCombine(
N)) {
17508 AddToWorklist(Fused.getNode());
17514 if (
SDValue R = combineFMulOrFDivWithIntPow2(
N))
17520template <
class MatchContextClass>
SDValue DAGCombiner::visitFMA(
SDNode *
N) {
17526 EVT VT =
N->getValueType(0);
17531 MatchContextClass matcher(DAG, TLI,
N);
17556 if (N0CFP && N0CFP->
isZero())
17558 if (N1CFP && N1CFP->
isZero())
17566 return matcher.getNode(
ISD::FADD,
DL, VT, N0, N2);
17571 return matcher.getNode(
ISD::FMA,
DL, VT, N1, N0, N2);
17573 bool CanReassociate =
17574 Options.UnsafeFPMath ||
N->getFlags().hasAllowReassociation();
17575 if (CanReassociate) {
17580 return matcher.getNode(
17589 return matcher.getNode(
17599 return matcher.getNode(
ISD::FADD,
DL, VT, N0, N2);
17604 AddToWorklist(RHSNeg.
getNode());
17605 return matcher.getNode(
ISD::FADD,
DL, VT, N2, RHSNeg);
17619 if (CanReassociate) {
17621 if (N1CFP && N0 == N2) {
17639 SDValue(
N, 0), DAG, LegalOperations, ForCodeSize))
17648 EVT VT =
N->getValueType(0);
17671 if (LegalDAG || (!UnsafeMath && !
Flags.hasAllowReciprocal()))
17675 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
17686 unsigned NumElts = 1;
17687 EVT VT =
N->getValueType(0);
17691 if (!MinUses || (N1->
use_size() * NumElts) < MinUses)
17697 for (
auto *U : N1->
users()) {
17698 if (
U->getOpcode() ==
ISD::FDIV &&
U->getOperand(1) == N1) {
17700 if (
U->getOperand(1).getOpcode() ==
ISD::FSQRT &&
17701 U->getOperand(0) ==
U->getOperand(1).getOperand(0) &&
17702 U->getFlags().hasAllowReassociation() &&
17703 U->getFlags().hasNoSignedZeros())
17708 if (UnsafeMath ||
U->getFlags().hasAllowReciprocal())
17715 if ((
Users.size() * NumElts) < MinUses)
17723 for (
auto *U :
Users) {
17724 SDValue Dividend =
U->getOperand(0);
17725 if (Dividend != FPOne) {
17727 Reciprocal, Flags);
17728 CombineTo(U, NewNode);
17729 }
else if (U != Reciprocal.
getNode()) {
17732 CombineTo(U, Reciprocal);
17741 EVT VT =
N->getValueType(0);
17756 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
17759 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17776 (
Options.UnsafeFPMath ||
Flags.hasAllowReciprocal()))) &&
17777 (!LegalOperations ||
17787 if (
Options.UnsafeFPMath ||
Flags.hasAllowReciprocal()) {
17827 A =
Y.getOperand(0);
17836 if (
SDValue Rsqrt = buildRsqrtEstimate(AAZ, Flags))
17840 recursivelyDeleteUnusedNodes(AAZ.
getNode());
17848 AddToWorklist(Div.
getNode());
17856 if (
SDValue RV = BuildDivEstimate(N0, N1, Flags))
17861 if ((
Options.NoSignedZerosFPMath ||
Flags.hasNoSignedZeros()) &&
17862 (
Options.UnsafeFPMath ||
Flags.hasAllowReassociation()))
17882 if (
SDValue R = combineFMulOrFDivWithIntPow2(
N))
17891 EVT VT =
N->getValueType(0);
17903 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17913 bool NeedsCopySign =
17937 if (!
Flags.hasApproximateFuncs() ||
17950 return buildSqrtEstimate(N0, Flags);
17965 if (YTy == MVT::f128)
17984 EVT VT =
N->getValueType(0);
17995 if (!
V.isNegative()) {
18049 EVT VT =
N->getValueType(0);
18059 if (!
Flags.hasNoSignedZeros() || !
Flags.hasNoInfs() || !
Flags.hasNoNaNs() ||
18060 !
Flags.hasApproximateFuncs())
18079 if (ExponentIs025 || ExponentIs075) {
18090 if ((!
Flags.hasNoSignedZeros() && ExponentIs025) || !
Flags.hasNoInfs() ||
18091 !
Flags.hasApproximateFuncs())
18124 EVT VT =
N->getValueType(0);
18145 EVT VT =
N->getValueType(0);
18193 EVT VT =
N->getValueType(0);
18231 EVT VT =
N->getValueType(0);
18237 EVT SrcVT = Src.getValueType();
18252 unsigned ActualSize = std::min(InputSize, OutputSize);
18261 return DAG.
getNode(ExtOp,
DL, VT, Src);
18272 EVT VT =
N->getValueType(0);
18288 EVT VT =
N->getValueType(0);
18304 EVT VT =
N->getValueType(0);
18323 EVT VT =
N->getValueType(0);
18336 const bool NIsTrunc =
N->getConstantOperandVal(1) == 1;
18374 AddToWorklist(Tmp.
getNode());
18378 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
18386 EVT VT =
N->getValueType(0);
18390 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
18410 if (
In.getValueType() == VT)
return In;
18424 CombineTo(
N, ExtLoad);
18433 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
18441 EVT VT =
N->getValueType(0);
18452 EVT VT =
N->getValueType(0);
18486 EVT VT =
N->getValueType(0);
18497 EVT VT =
N->getValueType(0);
18514 N->getFlags().hasNoSignedZeros()) && N0.
hasOneUse()) {
18519 if (
SDValue Cast = foldSignChangeInBitcast(
N))
18528 EVT VT =
N->getValueType(0);
18530 unsigned Opc =
N->getOpcode();
18552 return PropagatesNaN ?
N->getOperand(1) :
N->getOperand(0);
18561 if (IsMin == AF.
isNegative() && (!PropagatesNaN ||
Flags.hasNoNaNs()))
18562 return N->getOperand(1);
18568 if (IsMin != AF.
isNegative() && (PropagatesNaN ||
Flags.hasNoNaNs()))
18569 return N->getOperand(0);
18573 if (
SDValue SD = reassociateReduction(
18577 Opc,
SDLoc(
N), VT, N0, N1, Flags))
18585 EVT VT =
N->getValueType(0);
18594 return N->getOperand(0);
18601 if (
SDValue Cast = foldSignChangeInBitcast(
N))
18634 bool Updated =
false;
18646 return True || False;
18650 if (!IsAlwaysTrueOrFalse(
Cond, S1C)) {
18657 S1 =
S1->getOperand(0);
18689 if (
SDValue NewN1 = rebuildSetCC(N1))
18691 ChainHandle.getValue(), NewN1, N2,
N->getFlags());
18700 (
N.getOperand(0).hasOneUse() &&
18701 N.getOperand(0).getOpcode() ==
ISD::SRL))) {
18704 N =
N.getOperand(0);
18753 SDValue Tmp = visitXOR(
N.getNode());
18760 N = XORHandle.getValue();
18772 bool Equal =
false;
18777 Op0 =
N->getOperand(0);
18778 Op1 =
N->getOperand(1);
18782 EVT SetCCVT =
N.getValueType();
18802 SDValue CondLHS =
N->getOperand(2), CondRHS =
N->getOperand(3);
18812 CondLHS, CondRHS,
CC->get(),
SDLoc(
N),
18830 if (LD->isIndexed())
18832 EVT VT = LD->getMemoryVT();
18835 Ptr = LD->getBasePtr();
18836 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
18837 if (ST->isIndexed())
18839 EVT VT = ST->getMemoryVT();
18842 Ptr = ST->getBasePtr();
18845 if (LD->isIndexed())
18847 EVT VT = LD->getMemoryVT();
18851 Ptr = LD->getBasePtr();
18854 if (ST->isIndexed())
18856 EVT VT = ST->getMemoryVT();
18860 Ptr = ST->getBasePtr();
18874bool DAGCombiner::CombineToPreIndexedLoadStore(
SDNode *
N) {
18878 bool IsLoad =
true;
18879 bool IsMasked =
false;
18901 bool Swapped =
false;
18902 if (isa<ConstantSDNode>(BasePtr)) {
18921 if (isa<FrameIndexSDNode>(BasePtr) || isa<RegisterSDNode>(BasePtr))
18926 SDValue Val = IsMasked ? cast<MaskedStoreSDNode>(
N)->getValue()
18927 : cast<StoreSDNode>(
N)->getValue();
18930 if (Val == BasePtr)
18948 if (isa<ConstantSDNode>(
Offset))
18966 if (!isa<ConstantSDNode>(Op1)) {
18984 bool RealUse =
false;
19020 WorklistRemover DeadNodes(*
this);
19029 deleteAndRecombine(
N);
19035 for (
unsigned i = 0, e = OtherUses.
size(); i != e; ++i) {
19036 unsigned OffsetIdx = 1;
19037 if (OtherUses[i]->getOperand(OffsetIdx).
getNode() ==
BasePtr.getNode())
19040 BasePtr.getNode() &&
"Expected BasePtr operand");
19053 auto *CN = cast<ConstantSDNode>(OtherUses[i]->getOperand(OffsetIdx));
19054 const APInt &Offset0 = CN->getAPIntValue();
19056 int X0 = (OtherUses[i]->getOpcode() ==
ISD::SUB && OffsetIdx == 1) ? -1 : 1;
19057 int Y0 = (OtherUses[i]->getOpcode() ==
ISD::SUB && OffsetIdx == 0) ? -1 : 1;
19063 APInt CNV = Offset0;
19064 if (X0 < 0) CNV = -CNV;
19065 if (X1 * Y0 * Y1 < 0) CNV = CNV + Offset1;
19066 else CNV = CNV - Offset1;
19078 deleteAndRecombine(OtherUses[i]);
19083 deleteAndRecombine(
Ptr.getNode());
19084 AddToWorklist(
Result.getNode());
19105 if (isa<FrameIndexSDNode>(BasePtr) || isa<RegisterSDNode>(BasePtr))
19115 if (isa<MemSDNode>(
User)) {
19116 bool IsLoad =
true;
19117 bool IsMasked =
false;
19120 IsMasked, OtherPtr, TLI)) {
19146 IsMasked,
Ptr, TLI) ||
19180bool DAGCombiner::CombineToPostIndexedLoadStore(
SDNode *
N) {
19184 bool IsLoad =
true;
19185 bool IsMasked =
false;
19206 ++PostIndexedNodes;
19210 WorklistRemover DeadNodes(*
this);
19219 deleteAndRecombine(
N);
19223 Result.getValue(IsLoad ? 1 : 0));
19224 deleteAndRecombine(
Op);
19239 !cast<ConstantSDNode>(Inc)->isOpaque()) &&
19240 "Cannot split out indexing using opaque target constants");
19258 EVT STMemType =
ST->getMemoryVT();
19259 if (STType == STMemType)
19281 EVT LDMemType =
LD->getMemoryVT();
19282 EVT LDType =
LD->getValueType(0);
19284 "Attempting to extend value of non-matching type");
19285 if (LDType == LDMemType)
19288 switch (
LD->getExtensionType()) {
19324 if (!BasePtrST.equalBaseIndex(BasePtrLD, DAG,
Offset))
19327 GatherAllAliases(Store, Chain, Aliases);
19328 if (Aliases.
empty() ||
19329 (Aliases.
size() == 1 && Aliases.
front().getNode() == Store))
19338 if (BasePtrST.equalBaseIndex(BasePtrLD, DAG,
Offset))
19354 if (!ST || !
ST->isSimple() ||
ST->getAddressSpace() !=
LD->getAddressSpace())
19357 EVT LDType =
LD->getValueType(0);
19358 EVT LDMemType =
LD->getMemoryVT();
19359 EVT STMemType =
ST->getMemoryVT();
19360 EVT STType =
ST->getValue().getValueType();
19384 int64_t OrigOffset =
Offset;
19397 STCoversLD = (
Offset == 0) && LdMemSize == StMemSize;
19403 if (
LD->isIndexed()) {
19410 return CombineTo(LD, Ops, 3);
19412 return CombineTo(LD, Val, Chain);
19419 if (
Offset == 0 && LDType == STType && STMemType == LDMemType) {
19422 return ReplaceLd(LD,
ST->getValue(), Chain);
19430 SDLoc(ST), STType);
19432 return ReplaceLd(LD, Val, Chain);
19450 if (
LD->getBasePtr().isUndef() ||
Offset != 0)
19455 if (!getTruncatedStoreValue(ST, Val))
19459 if (STMemType != LDMemType) {
19467 if (!extendLoadedValueToExtension(LD, Val))
19469 return ReplaceLd(LD, Val, Chain);
19474 deleteAndRecombine(Val.
getNode());
19487 if (
LD->isSimple()) {
19488 if (
N->getValueType(1) == MVT::Other) {
19490 if (!
N->hasAnyUseOfValue(0)) {
19498 dbgs() <<
"\nWith chain: "; Chain.
dump(&DAG);
19500 WorklistRemover DeadNodes(*
this);
19502 AddUsersToWorklist(Chain.
getNode());
19503 if (
N->use_empty())
19504 deleteAndRecombine(
N);
19510 assert(
N->getValueType(2) == MVT::Other &&
"Malformed indexed loads?");
19518 if (!
N->hasAnyUseOfValue(0) && (CanSplitIdx || !
N->hasAnyUseOfValue(1))) {
19521 if (
N->hasAnyUseOfValue(1) && CanSplitIdx) {
19522 Index = SplitIndexingFromLoad(LD);
19525 AddUsersToWorklist(
N);
19529 dbgs() <<
"\nWith: ";
Undef.dump(&DAG);
19530 dbgs() <<
" and 2 other values\n");
19531 WorklistRemover DeadNodes(*
this);
19535 deleteAndRecombine(
N);
19543 if (
auto V = ForwardStoreValueToDirectLoad(LD))
19550 if (*Alignment >
LD->getAlign() &&
19551 isAligned(*Alignment,
LD->getSrcValueOffset())) {
19553 LD->getExtensionType(),
SDLoc(
N),
LD->getValueType(0), Chain,
Ptr,
19554 LD->getPointerInfo(),
LD->getMemoryVT(), *Alignment,
19555 LD->getMemOperand()->getFlags(),
LD->getAAInfo());
19563 if (
LD->isUnindexed()) {
19565 SDValue BetterChain = FindBetterChain(LD, Chain);
19568 if (Chain != BetterChain) {
19574 BetterChain,
Ptr,
LD->getMemOperand());
19577 LD->getValueType(0),
19578 BetterChain,
Ptr,
LD->getMemoryVT(),
19579 LD->getMemOperand());
19584 MVT::Other, Chain, ReplLoad.
getValue(1));
19587 return CombineTo(
N, ReplLoad.
getValue(0), Token);
19592 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
19597 if (SliceUpLoad(
N))
19617struct LoadedSlice {
19621 bool ForCodeSize =
false;
19624 unsigned Loads = 0;
19625 unsigned Truncates = 0;
19626 unsigned CrossRegisterBanksCopies = 0;
19627 unsigned ZExts = 0;
19628 unsigned Shift = 0;
19630 explicit Cost(
bool ForCodeSize) : ForCodeSize(ForCodeSize) {}
19633 Cost(
const LoadedSlice &LS,
bool ForCodeSize)
19634 : ForCodeSize(ForCodeSize), Loads(1) {
19635 EVT TruncType =
LS.Inst->getValueType(0);
19636 EVT LoadedType =
LS.getLoadedType();
19637 if (TruncType != LoadedType &&
19638 !
LS.DAG->getTargetLoweringInfo().isZExtFree(LoadedType, TruncType))
19646 void addSliceGain(
const LoadedSlice &LS) {
19655 if (
LS.canMergeExpensiveCrossRegisterBankCopy())
19656 ++CrossRegisterBanksCopies;
19660 Loads +=
RHS.Loads;
19661 Truncates +=
RHS.Truncates;
19662 CrossRegisterBanksCopies +=
RHS.CrossRegisterBanksCopies;
19663 ZExts +=
RHS.ZExts;
19664 Shift +=
RHS.Shift;
19669 return Loads ==
RHS.Loads && Truncates ==
RHS.Truncates &&
19670 CrossRegisterBanksCopies ==
RHS.CrossRegisterBanksCopies &&
19671 ZExts ==
RHS.ZExts && Shift ==
RHS.Shift;
19679 unsigned ExpensiveOpsLHS = Loads + CrossRegisterBanksCopies;
19680 unsigned ExpensiveOpsRHS =
RHS.Loads +
RHS.CrossRegisterBanksCopies;
19683 if (!ForCodeSize && ExpensiveOpsLHS != ExpensiveOpsRHS)
19684 return ExpensiveOpsLHS < ExpensiveOpsRHS;
19685 return (Truncates + ZExts + Shift + ExpensiveOpsLHS) <
19686 (
RHS.Truncates +
RHS.ZExts +
RHS.Shift + ExpensiveOpsRHS);
19712 : Inst(Inst), Origin(Origin), Shift(Shift), DAG(DAG) {}
19717 APInt getUsedBits()
const {
19722 assert(Origin &&
"No original load to compare against.");
19724 assert(Inst &&
"This slice is not bound to an instruction");
19726 "Extracted slice is bigger than the whole type!");
19728 UsedBits.setAllBits();
19729 UsedBits = UsedBits.zext(
BitWidth);
19730 UsedBits <<= Shift;
19735 unsigned getLoadedSize()
const {
19736 unsigned SliceSize = getUsedBits().popcount();
19737 assert(!(SliceSize & 0x7) &&
"Size is not a multiple of a byte.");
19738 return SliceSize / 8;
19743 EVT getLoadedType()
const {
19744 assert(DAG &&
"Missing context");
19759 bool isLegal()
const {
19761 if (!Origin || !Inst || !DAG)
19771 EVT SliceType = getLoadedType();
19782 if (PtrType == MVT::Untyped || PtrType.
isExtended())
19795 if (TruncateType != SliceType &&
19805 uint64_t getOffsetFromBase()
const {
19806 assert(DAG &&
"Missing context.");
19808 assert(!(Shift & 0x7) &&
"Shifts not aligned on Bytes are not supported.");
19812 "The size of the original loaded type is not a multiple of a"
19817 "Invalid shift amount for given loaded size");
19830 assert(Inst && Origin &&
"Unable to replace a non-existing slice.");
19834 int64_t
Offset =
static_cast<int64_t
>(getOffsetFromBase());
19835 assert(
Offset >= 0 &&
"Offset too big to fit in int64_t!");
19845 EVT SliceType = getLoadedType();
19855 if (SliceType != FinalType)
19865 bool canMergeExpensiveCrossRegisterBankCopy()
const {
19871 assert(DAG &&
"Missing context");
19873 EVT ResVT =
User->getValueType(0);
19887 if (!
TRI ||
TRI->getCommonSubClass(ArgRC, ResRC))
19892 unsigned IsFast = 0;
19933 const LoadedSlice &Second) {
19935 "Unable to match different memory origins.");
19937 assert((UsedBits & Second.getUsedBits()) == 0 &&
19938 "Slices are not supposed to overlap.");
19939 UsedBits |= Second.getUsedBits();
19948 LoadedSlice::Cost &GlobalLSCost) {
19949 unsigned NumberOfSlices = LoadedSlices.
size();
19951 if (NumberOfSlices < 2)
19956 llvm::sort(LoadedSlices, [](
const LoadedSlice &
LHS,
const LoadedSlice &
RHS) {
19957 assert(
LHS.Origin ==
RHS.Origin &&
"Different bases not implemented.");
19958 return LHS.getOffsetFromBase() <
RHS.getOffsetFromBase();
19960 const TargetLowering &TLI = LoadedSlices[0].DAG->getTargetLoweringInfo();
19963 const LoadedSlice *
First =
nullptr;
19964 const LoadedSlice *Second =
nullptr;
19965 for (
unsigned CurrSlice = 0; CurrSlice < NumberOfSlices; ++CurrSlice,
19968 Second = &LoadedSlices[CurrSlice];
19975 EVT LoadedType =
First->getLoadedType();
19978 if (LoadedType != Second->getLoadedType())
19982 Align RequiredAlignment;
19983 if (!TLI.hasPairedLoad(LoadedType, RequiredAlignment)) {
19989 if (
First->getAlign() < RequiredAlignment)
19996 assert(GlobalLSCost.Loads > 0 &&
"We save more loads than we created!");
19997 --GlobalLSCost.Loads;
20014 const APInt &UsedBits,
bool ForCodeSize) {
20015 unsigned NumberOfSlices = LoadedSlices.
size();
20017 return NumberOfSlices > 1;
20020 if (NumberOfSlices != 2)
20028 LoadedSlice::Cost OrigCost(ForCodeSize), GlobalSlicingCost(ForCodeSize);
20030 OrigCost.Loads = 1;
20031 for (
unsigned CurrSlice = 0; CurrSlice < NumberOfSlices; ++CurrSlice) {
20032 const LoadedSlice &LS = LoadedSlices[CurrSlice];
20034 LoadedSlice::Cost SliceCost(LS, ForCodeSize);
20035 GlobalSlicingCost += SliceCost;
20039 OrigCost.addSliceGain(LS);
20044 return OrigCost > GlobalSlicingCost;
20053bool DAGCombiner::SliceUpLoad(
SDNode *
N) {
20059 !
LD->getValueType(0).isInteger())
20065 if (
LD->getValueType(0).isScalableVector())
20070 APInt UsedBits(
LD->getValueSizeInBits(0), 0);
20077 for (
SDUse &U :
LD->uses()) {
20079 if (
U.getResNo() != 0)
20083 unsigned Shift = 0;
20088 Shift =
User->getConstantOperandVal(1);
20101 unsigned Width =
User->getValueSizeInBits(0);
20106 LoadedSlice
LS(
User, LD, Shift, &DAG);
20107 APInt CurrentUsedBits =
LS.getUsedBits();
20110 if ((CurrentUsedBits & UsedBits) != 0)
20113 UsedBits |= CurrentUsedBits;
20134 for (
const LoadedSlice &LS : LoadedSlices) {
20136 CombineTo(
LS.Inst, SliceInst,
true);
20140 "It takes more than a zext to get to the loaded slice!!");
20147 AddToWorklist(Chain.
getNode());
20154static std::pair<unsigned, unsigned>
20156 std::pair<unsigned, unsigned> Result(0, 0);
20160 !isa<ConstantSDNode>(V->getOperand(1)) ||
20165 LoadSDNode *LD = cast<LoadSDNode>(V->getOperand(0));
20166 if (LD->getBasePtr() !=
Ptr)
return Result;
20169 if (V.getValueType() != MVT::i16 &&
20170 V.getValueType() != MVT::i32 &&
20171 V.getValueType() != MVT::i64)
20177 uint64_t NotMask = ~cast<ConstantSDNode>(V->getOperand(1))->getSExtValue();
20179 if (NotMaskLZ & 7)
return Result;
20181 if (NotMaskTZ & 7)
return Result;
20182 if (NotMaskLZ == 64)
return Result;
20189 if (V.getValueType() != MVT::i64 && NotMaskLZ)
20190 NotMaskLZ -= 64-V.getValueSizeInBits();
20192 unsigned MaskedBytes = (V.getValueSizeInBits()-NotMaskLZ-NotMaskTZ)/8;
20193 switch (MaskedBytes) {
20197 default:
return Result;
20202 if (NotMaskTZ && NotMaskTZ/8 % MaskedBytes)
return Result;
20211 if (!LD->isOperandOf(Chain.
getNode()))
20216 Result.first = MaskedBytes;
20217 Result.second = NotMaskTZ/8;
20228 unsigned NumBytes = MaskInfo.first;
20229 unsigned ByteShift = MaskInfo.second;
20235 ByteShift*8, (ByteShift+NumBytes)*8);
20244 bool UseTruncStore;
20245 if (DC->isTypeLegal(VT))
20246 UseTruncStore =
false;
20249 UseTruncStore =
true;
20275 StOffset = ByteShift;
20306 if (!
ST->isSimple())
20314 if (
ST->isTruncatingStore() || VT.
isVector())
20317 unsigned Opc =
Value.getOpcode();
20329 std::pair<unsigned, unsigned> MaskedLoad;
20331 if (MaskedLoad.first)
20333 Value.getOperand(1), ST,
this))
20338 if (MaskedLoad.first)
20340 Value.getOperand(0), ST,
this))
20354 if (
LD->getBasePtr() !=
Ptr ||
20355 LD->getPointerInfo().getAddrSpace() !=
20356 ST->getPointerInfo().getAddrSpace())
20365 if (Imm == 0 ||
Imm.isAllOnes())
20370 unsigned BitsPerByteMask = 7u;
20371 unsigned LSB =
Imm.countr_zero() & ~BitsPerByteMask;
20372 unsigned MSB = (
Imm.getActiveBits() - 1) | BitsPerByteMask;
20400 unsigned ShAmt = 0;
20402 for (; ShAmt + NewBW <= VTStoreSize; ShAmt += 8) {
20406 if (ShAmt + NewBW < MSB)
20411 ? VTStoreSize - NewBW - ShAmt
20413 PtrOff = PtrAdjustmentInBits / 8;
20416 unsigned IsFast = 0;
20419 LD->getAddressSpace(), NewAlign,
20420 LD->getMemOperand()->getFlags(), &IsFast) &&
20425 if (ShAmt + NewBW > VTStoreSize)
20428 APInt NewImm =
Imm.lshr(ShAmt).trunc(NewBW);
20436 LD->getPointerInfo().getWithOffset(PtrOff), NewAlign,
20437 LD->getMemOperand()->getFlags(),
LD->getAAInfo());
20442 ST->getPointerInfo().getWithOffset(PtrOff), NewAlign);
20444 AddToWorklist(NewPtr.
getNode());
20445 AddToWorklist(NewLD.
getNode());
20446 AddToWorklist(NewVal.
getNode());
20447 WorklistRemover DeadNodes(*
this);
20465 EVT VT =
LD->getMemoryVT();
20467 LD->isNonTemporal() ||
ST->isNonTemporal() ||
20468 LD->getPointerInfo().getAddrSpace() != 0 ||
20469 ST->getPointerInfo().getAddrSpace() != 0)
20479 unsigned FastLD = 0, FastST = 0;
20486 *
LD->getMemOperand(), &FastLD) ||
20488 *
ST->getMemOperand(), &FastST) ||
20489 !FastLD || !FastST)
20493 LD->getBasePtr(),
LD->getMemOperand());
20496 ST->getBasePtr(),
ST->getMemOperand());
20498 AddToWorklist(NewLD.
getNode());
20499 AddToWorklist(NewST.
getNode());
20500 WorklistRemover DeadNodes(*
this);
20522bool DAGCombiner::isMulAddWithConstProfitable(
SDNode *MulNode,
SDValue AddNode,
20534 if (
User == MulNode)
20557 if (OtherOp == MulVar)
20585 unsigned NumStores) {
20588 SDLoc StoreDL(StoreNodes[0].MemNode);
20590 for (
unsigned i = 0; i < NumStores; ++i) {
20591 Visited.
insert(StoreNodes[i].MemNode);
20595 for (
unsigned i = 0; i < NumStores; ++i) {
20596 if (Visited.
insert(StoreNodes[i].MemNode->getChain().getNode()).second)
20597 Chains.
push_back(StoreNodes[i].MemNode->getChain());
20600 assert(!Chains.
empty() &&
"Chain should have generated a chain");
20605 const Value *UnderlyingObj =
nullptr;
20606 for (
const auto &
MemOp : StoreNodes) {
20618 if (UnderlyingObj && UnderlyingObj != Obj)
20621 if (!UnderlyingObj)
20622 UnderlyingObj = Obj;
20628bool DAGCombiner::mergeStoresOfConstantsOrVecElts(
20630 bool IsConstantSrc,
bool UseVector,
bool UseTrunc) {
20635 assert((!UseTrunc || !UseVector) &&
20636 "This optimization cannot emit a vector truncating store");
20639 SDLoc DL(StoreNodes[0].MemNode);
20642 unsigned SizeInBits = NumStores * ElementSizeBits;
20645 std::optional<MachineMemOperand::Flags>
Flags;
20647 for (
unsigned I = 0;
I != NumStores; ++
I) {
20648 StoreSDNode *St = cast<StoreSDNode>(StoreNodes[
I].MemNode);
20663 unsigned Elts = NumStores * NumMemElts;
20671 if (IsConstantSrc) {
20673 for (
unsigned I = 0;
I != NumStores; ++
I) {
20674 StoreSDNode *St = cast<StoreSDNode>(StoreNodes[
I].MemNode);
20682 auto *
C = dyn_cast<ConstantSDNode>(Val);
20692 .zextOrTrunc(ElementSizeBits),
20702 DL, StoreTy, BuildVector);
20705 for (
unsigned i = 0; i < NumStores; ++i) {
20706 StoreSDNode *St = cast<StoreSDNode>(StoreNodes[i].MemNode);
20743 assert(IsConstantSrc &&
"Merged vector elements should use vector store");
20745 APInt StoreInt(SizeInBits, 0);
20750 for (
unsigned i = 0; i < NumStores; ++i) {
20751 unsigned Idx = IsLE ? (NumStores - 1 - i) : i;
20754 SDValue Val = St->getValue();
20756 StoreInt <<= ElementSizeBits;
20758 StoreInt |=
C->getAPIntValue()
20759 .zextOrTrunc(ElementSizeBits)
20760 .zextOrTrunc(SizeInBits);
20762 StoreInt |=
C->getValueAPF()
20764 .zextOrTrunc(ElementSizeBits)
20765 .zextOrTrunc(SizeInBits);
20783 SDValue NewChain = getMergeStoreChains(StoreNodes, NumStores);
20784 bool CanReusePtrInfo = hasSameUnderlyingObj(StoreNodes);
20798 FirstInChain->
getAlign(), *Flags, AAInfo);
20800 EVT LegalizedStoredValTy =
20802 unsigned LegalizedStoreSize = LegalizedStoredValTy.
getSizeInBits();
20805 DAG.
getConstant(
C->getAPIntValue().zextOrTrunc(LegalizedStoreSize),
DL,
20806 LegalizedStoredValTy);
20808 NewChain,
DL, ExtendedStoreVal, FirstInChain->
getBasePtr(),
20817 for (
unsigned i = 0; i < NumStores; ++i)
20818 CombineTo(StoreNodes[i].MemNode, NewStore);
20820 AddToWorklist(NewChain.
getNode());
20825DAGCombiner::getStoreMergeCandidates(
StoreSDNode *St,
20831 if (!
BasePtr.getBase().getNode() ||
BasePtr.getBase().isUndef())
20835 StoreSource StoreSrc = getStoreSource(Val);
20836 assert(StoreSrc != StoreSource::Unknown &&
"Expected known source for store");
20842 if (StoreSrc == StoreSource::Load) {
20843 auto *Ld = cast<LoadSDNode>(Val);
20845 LoadVT = Ld->getMemoryVT();
20847 if (MemVT != LoadVT)
20850 if (!Ld->hasNUsesOfValue(1, 0))
20854 if (!Ld->isSimple() || Ld->isIndexed())
20858 int64_t &
Offset) ->
bool {
20861 if (!
Other->isSimple() ||
Other->isIndexed())
20871 :
Other->getMemoryVT() != MemVT;
20872 switch (StoreSrc) {
20873 case StoreSource::Load: {
20877 auto *OtherLd = dyn_cast<LoadSDNode>(OtherBC);
20881 if (LoadVT != OtherLd->getMemoryVT())
20884 if (!OtherLd->hasNUsesOfValue(1, 0))
20888 if (!OtherLd->isSimple() || OtherLd->isIndexed())
20891 if (cast<LoadSDNode>(Val)->isNonTemporal() != OtherLd->isNonTemporal())
20896 if (!(LBasePtr.equalBaseIndex(LPtr, DAG)))
20900 case StoreSource::Constant:
20903 if (getStoreSource(OtherBC) != StoreSource::Constant)
20906 case StoreSource::Extract:
20908 if (
Other->isTruncatingStore())
20941 if (ChainsWithoutMergeableStores.
contains(RootNode))
20946 auto OverLimitInDependenceCheck = [&](
SDNode *StoreNode,
20947 SDNode *RootNode) ->
bool {
20948 auto RootCount = StoreRootCountMap.
find(StoreNode);
20949 return RootCount != StoreRootCountMap.
end() &&
20950 RootCount->second.first == RootNode &&
20954 auto TryToAddCandidate = [&](
SDUse &
Use) {
20958 if (
auto *OtherStore = dyn_cast<StoreSDNode>(
Use.
getUser())) {
20961 if (CandidateMatch(OtherStore,
Ptr, PtrDiff) &&
20962 !OverLimitInDependenceCheck(OtherStore, RootNode))
20963 StoreNodes.
push_back(MemOpLink(OtherStore, PtrDiff));
20967 unsigned NumNodesExplored = 0;
20968 const unsigned MaxSearchNodes = 1024;
20969 if (
auto *Ldn = dyn_cast<LoadSDNode>(RootNode)) {
20970 RootNode = Ldn->getChain().getNode();
20972 if (ChainsWithoutMergeableStores.
contains(RootNode))
20975 I != E && NumNodesExplored < MaxSearchNodes; ++
I, ++NumNodesExplored) {
20977 if (
I->getOperandNo() == 0 && isa<LoadSDNode>(
User)) {
20979 TryToAddCandidate(U2);
20982 if (
I->getOperandNo() == 0 && isa<StoreSDNode>(
User)) {
20983 TryToAddCandidate(*
I);
20988 I != E && NumNodesExplored < MaxSearchNodes; ++
I, ++NumNodesExplored)
20989 TryToAddCandidate(*
I);
20998bool DAGCombiner::checkMergeStoreCandidatesForDependencies(
21014 while (!Worklist.
empty()) {
21016 if (!Visited.
insert(
N).second)
21025 unsigned int Max = 1024 + Visited.
size();
21027 for (
unsigned i = 0; i < NumStores; ++i) {
21028 SDNode *
N = StoreNodes[i].MemNode;
21049 for (
unsigned i = 0; i < NumStores; ++i)
21055 if (Visited.
size() >= Max) {
21056 auto &RootCount = StoreRootCountMap[StoreNodes[i].MemNode];
21057 if (RootCount.first == RootNode)
21058 RootCount.second++;
21060 RootCount = {RootNode, 1};
21069 int64_t ElementSizeBytes)
const {
21072 size_t StartIdx = 0;
21073 while ((StartIdx + 1 < StoreNodes.
size()) &&
21074 StoreNodes[StartIdx].OffsetFromBase + ElementSizeBytes !=
21075 StoreNodes[StartIdx + 1].OffsetFromBase)
21079 if (StartIdx + 1 >= StoreNodes.
size())
21088 unsigned NumConsecutiveStores = 1;
21089 int64_t StartAddress = StoreNodes[0].OffsetFromBase;
21092 for (
unsigned i = 1, e = StoreNodes.
size(); i < e; ++i) {
21093 int64_t CurrAddress = StoreNodes[i].OffsetFromBase;
21094 if (CurrAddress - StartAddress != (ElementSizeBytes * i))
21096 NumConsecutiveStores = i + 1;
21098 if (NumConsecutiveStores > 1)
21099 return NumConsecutiveStores;
21107bool DAGCombiner::tryStoreMergeOfConstants(
21109 EVT MemVT,
SDNode *RootNode,
bool AllowVectors) {
21114 bool MadeChange =
false;
21117 while (NumConsecutiveStores >= 2) {
21121 unsigned LastLegalType = 1;
21122 unsigned LastLegalVectorType = 1;
21123 bool LastIntegerTrunc =
false;
21124 bool NonZero =
false;
21125 unsigned FirstZeroAfterNonZero = NumConsecutiveStores;
21126 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
21127 StoreSDNode *
ST = cast<StoreSDNode>(StoreNodes[i].MemNode);
21129 bool IsElementZero =
false;
21131 IsElementZero =
C->isZero();
21133 IsElementZero =
C->getConstantFPValue()->isNullValue();
21135 IsElementZero =
true;
21136 if (IsElementZero) {
21137 if (NonZero && FirstZeroAfterNonZero == NumConsecutiveStores)
21138 FirstZeroAfterNonZero = i;
21140 NonZero |= !IsElementZero;
21143 unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
21145 unsigned IsFast = 0;
21157 LastIntegerTrunc =
false;
21158 LastLegalType = i + 1;
21162 EVT LegalizedStoredValTy =
21170 LastIntegerTrunc =
true;
21171 LastLegalType = i + 1;
21180 unsigned Elts = (i + 1) * NumMemElts;
21187 LastLegalVectorType = i + 1;
21191 bool UseVector = (LastLegalVectorType > LastLegalType) && AllowVectors;
21192 unsigned NumElem = (UseVector) ? LastLegalVectorType : LastLegalType;
21193 bool UseTrunc = LastIntegerTrunc && !UseVector;
21205 unsigned NumSkip = 1;
21206 while ((NumSkip < NumConsecutiveStores) &&
21207 (NumSkip < FirstZeroAfterNonZero) &&
21208 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
21212 NumConsecutiveStores -= NumSkip;
21217 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
21220 NumConsecutiveStores -= NumElem;
21224 MadeChange |= mergeStoresOfConstantsOrVecElts(StoreNodes, MemVT, NumElem,
21226 UseVector, UseTrunc);
21230 NumConsecutiveStores -= NumElem;
21235bool DAGCombiner::tryStoreMergeOfExtracts(
21241 bool MadeChange =
false;
21244 while (NumConsecutiveStores >= 2) {
21248 unsigned NumStoresToMerge = 1;
21249 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
21251 unsigned Elts = (i + 1) * NumMemElts;
21253 unsigned IsFast = 0;
21264 NumStoresToMerge = i + 1;
21269 if (NumStoresToMerge < 2) {
21276 unsigned NumSkip = 1;
21277 while ((NumSkip < NumConsecutiveStores) &&
21278 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
21282 NumConsecutiveStores -= NumSkip;
21287 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumStoresToMerge,
21290 StoreNodes.
begin() + NumStoresToMerge);
21291 NumConsecutiveStores -= NumStoresToMerge;
21295 MadeChange |= mergeStoresOfConstantsOrVecElts(
21296 StoreNodes, MemVT, NumStoresToMerge,
false,
21299 StoreNodes.
erase(StoreNodes.
begin(), StoreNodes.
begin() + NumStoresToMerge);
21300 NumConsecutiveStores -= NumStoresToMerge;
21306 unsigned NumConsecutiveStores,
EVT MemVT,
21307 SDNode *RootNode,
bool AllowVectors,
21308 bool IsNonTemporalStore,
21309 bool IsNonTemporalLoad) {
21314 bool MadeChange =
false;
21323 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
21324 StoreSDNode *St = cast<StoreSDNode>(StoreNodes[i].MemNode);
21330 int64_t LdOffset = 0;
21331 if (LdBasePtr.
getBase().getNode()) {
21333 if (!LdBasePtr.equalBaseIndex(LdPtr, DAG, LdOffset))
21341 LoadNodes.
push_back(MemOpLink(Ld, LdOffset));
21344 while (NumConsecutiveStores >= 2 && LoadNodes.
size() >= 2) {
21345 Align RequiredAlignment;
21346 bool NeedRotate =
false;
21347 if (LoadNodes.
size() == 2) {
21351 StoreNodes[0].MemNode->getAlign() >= RequiredAlignment) {
21357 int64_t Offset0 = LoadNodes[0].OffsetFromBase;
21358 int64_t Offset1 = LoadNodes[1].OffsetFromBase;
21360 if (Offset0 - Offset1 == ElementSizeBytes &&
21370 LoadSDNode *FirstLoad = cast<LoadSDNode>(LoadNodes[0].MemNode);
21376 unsigned LastConsecutiveLoad = 1;
21379 unsigned LastLegalVectorType = 1;
21380 unsigned LastLegalIntegerType = 1;
21381 bool isDereferenceable =
true;
21382 bool DoIntegerTruncate =
false;
21383 int64_t StartAddress = LoadNodes[0].OffsetFromBase;
21385 for (
unsigned i = 1; i < LoadNodes.
size(); ++i) {
21387 if (LoadNodes[i].MemNode->getChain() != LoadChain)
21390 int64_t CurrAddress = LoadNodes[i].OffsetFromBase;
21391 if (CurrAddress - StartAddress != (ElementSizeBytes * i))
21393 LastConsecutiveLoad = i;
21395 if (isDereferenceable && !LoadNodes[i].MemNode->isDereferenceable())
21396 isDereferenceable =
false;
21399 unsigned Elts = (i + 1) * NumMemElts;
21406 unsigned IsFastSt = 0;
21407 unsigned IsFastLd = 0;
21421 LastLegalVectorType = i + 1;
21425 unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
21436 LastLegalIntegerType = i + 1;
21437 DoIntegerTruncate =
false;
21454 LastLegalIntegerType = i + 1;
21455 DoIntegerTruncate =
true;
21463 LastLegalVectorType > LastLegalIntegerType && AllowVectors;
21464 unsigned LastLegalType =
21465 std::max(LastLegalVectorType, LastLegalIntegerType);
21469 unsigned NumElem = std::min(NumConsecutiveStores, LastConsecutiveLoad + 1);
21470 NumElem = std::min(LastLegalType, NumElem);
21481 unsigned NumSkip = 1;
21482 while ((NumSkip < LoadNodes.
size()) &&
21483 (LoadNodes[NumSkip].MemNode->getAlign() <= FirstLoadAlign) &&
21484 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
21488 NumConsecutiveStores -= NumSkip;
21493 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
21497 NumConsecutiveStores -= NumElem;
21506 unsigned Elts = NumElem * NumMemElts;
21509 unsigned SizeInBits = NumElem * ElementSizeBytes * 8;
21513 SDLoc LoadDL(LoadNodes[0].MemNode);
21514 SDLoc StoreDL(StoreNodes[0].MemNode);
21519 SDValue NewStoreChain = getMergeStoreChains(StoreNodes, NumElem);
21520 bool CanReusePtrInfo = hasSameUnderlyingObj(StoreNodes);
21521 AddToWorklist(NewStoreChain.
getNode());
21526 if (IsNonTemporalLoad)
21538 if (UseVectorTy || !DoIntegerTruncate) {
21544 unsigned LoadWidth = ElementSizeBytes * 8 * 2;
21546 "Unexpected type for rotate-able load pair");
21553 NewStoreChain, StoreDL, StoreOp, FirstInChain->
getBasePtr(),
21556 FirstStoreAlign, StMMOFlags);
21563 FirstLoadAlign, LdMMOFlags);
21565 NewStoreChain, StoreDL, NewLoad, FirstInChain->
getBasePtr(),
21568 JointMemOpVT, FirstInChain->
getAlign(),
21573 for (
unsigned i = 0; i < NumElem; ++i) {
21574 LoadSDNode *Ld = cast<LoadSDNode>(LoadNodes[i].MemNode);
21581 for (
unsigned i = 0; i < NumElem; ++i) {
21582 SDValue Val = StoreNodes[i].MemNode->getOperand(1);
21583 CombineTo(StoreNodes[i].MemNode, NewStore);
21585 recursivelyDeleteUnusedNodes(Val.
getNode());
21591 NumConsecutiveStores -= NumElem;
21596bool DAGCombiner::mergeConsecutiveStores(
StoreSDNode *St) {
21612 if (ElementSizeBytes * 8 != (int64_t)MemVT.
getSizeInBits())
21618 const StoreSource StoreSrc = getStoreSource(StoredVal);
21619 if (StoreSrc == StoreSource::Unknown)
21624 SDNode *RootNode = getStoreMergeCandidates(St, StoreNodes);
21627 if (StoreNodes.
size() < 2)
21632 llvm::sort(StoreNodes, [](MemOpLink LHS, MemOpLink RHS) {
21633 return LHS.OffsetFromBase <
RHS.OffsetFromBase;
21637 Attribute::NoImplicitFloat);
21639 bool IsNonTemporalLoad = StoreSrc == StoreSource::Load &&
21640 cast<LoadSDNode>(StoredVal)->isNonTemporal();
21649 bool MadeChange =
false;
21650 while (StoreNodes.
size() > 1) {
21651 unsigned NumConsecutiveStores =
21652 getConsecutiveStores(StoreNodes, ElementSizeBytes);
21654 if (NumConsecutiveStores == 0)
21658 assert(NumConsecutiveStores >= 2 &&
"Expected at least 2 stores");
21659 switch (StoreSrc) {
21660 case StoreSource::Constant:
21661 MadeChange |= tryStoreMergeOfConstants(StoreNodes, NumConsecutiveStores,
21662 MemVT, RootNode, AllowVectors);
21665 case StoreSource::Extract:
21666 MadeChange |= tryStoreMergeOfExtracts(StoreNodes, NumConsecutiveStores,
21670 case StoreSource::Load:
21671 MadeChange |= tryStoreMergeOfLoads(StoreNodes, NumConsecutiveStores,
21672 MemVT, RootNode, AllowVectors,
21673 IsNonTemporalStore, IsNonTemporalLoad);
21683 ChainsWithoutMergeableStores.
insert(RootNode);
21693 if (
ST->isTruncatingStore()) {
21695 ST->getBasePtr(),
ST->getMemoryVT(),
21696 ST->getMemOperand());
21698 ReplStore = DAG.
getStore(BetterChain, SL,
ST->getValue(),
ST->getBasePtr(),
21699 ST->getMemOperand());
21704 MVT::Other,
ST->getChain(), ReplStore);
21707 AddToWorklist(Token.
getNode());
21710 return CombineTo(ST, Token,
false);
21744 if ((
isTypeLegal(MVT::i32) && !LegalOperations &&
ST->isSimple()) ||
21747 bitcastToAPInt().getZExtValue(),
SDLoc(CFP),
21754 if ((TLI.
isTypeLegal(MVT::i64) && !LegalOperations &&
21758 getZExtValue(),
SDLoc(CFP), MVT::i64);
21760 Ptr,
ST->getMemOperand());
21778 ST->getOriginalAlign(), MMOFlags, AAInfo);
21781 ST->getPointerInfo().getWithOffset(4),
21782 ST->getOriginalAlign(), MMOFlags, AAInfo);
21811 EltVT !=
Value.getOperand(0).getValueType().getVectorElementType())
21814 auto *Ld = dyn_cast<LoadSDNode>(
Value.getOperand(0));
21825 ST->getAlign(),
ST->getMemOperand()->getFlags(),
21835 if (
auto *CIdx = dyn_cast<ConstantSDNode>(
Idx)) {
21836 unsigned COffset = CIdx->getSExtValue() * EltVT.
getSizeInBits() / 8;
21838 PointerInfo =
ST->getPointerInfo().getWithOffset(COffset);
21843 return DAG.
getStore(Chain,
DL, Elt, NewPtr, PointerInfo,
ST->getAlign(),
21844 ST->getMemOperand()->getFlags());
21851 EVT MemVT =
ST->getMemoryVT();
21874 ST->isUnindexed()) {
21875 EVT SVT =
Value.getOperand(0).getValueType();
21882 if (((!LegalOperations &&
ST->isSimple()) ||
21885 DAG, *
ST->getMemOperand())) {
21887 ST->getMemOperand());
21892 if (
Value.isUndef() &&
ST->isUnindexed() && !
ST->isVolatile())
21899 if (*Alignment >
ST->getAlign() &&
21900 isAligned(*Alignment,
ST->getSrcValueOffset())) {
21903 ST->getMemoryVT(), *Alignment,
21904 ST->getMemOperand()->getFlags(),
ST->getAAInfo());
21914 if (
SDValue NewST = TransformFPLoadStorePair(
N))
21918 if (
SDValue Store = mergeTruncStores(ST))
21921 if (
ST->isUnindexed()) {
21924 if (findBetterNeighborChains(ST)) {
21929 Chain =
ST->getChain();
21933 if (
ST->isTruncatingStore() &&
ST->isUnindexed() &&
21934 Value.getValueType().isInteger() &&
21935 (!isa<ConstantSDNode>(
Value) ||
21936 !cast<ConstantSDNode>(
Value)->isOpaque())) {
21941 Value.getOperand(0).getValueType() ==
ST->getMemoryVT() &&
21944 ST->getMemOperand());
21946 APInt TruncDemandedBits =
21948 ST->getMemoryVT().getScalarSizeInBits());
21952 AddToWorklist(
Value.getNode());
21969 ST->getMemOperand());
21973 if (
auto *Cst = dyn_cast<ConstantSDNode>(
Value))
21974 if (!Cst->isOpaque()) {
21975 const APInt &CValue = Cst->getAPIntValue();
21976 APInt NewVal = CValue & TruncDemandedBits;
21977 if (NewVal != CValue) {
21981 ST->getMemoryVT(),
ST->getMemOperand());
21993 if (
auto *Ld = dyn_cast<LoadSDNode>(TruncVal)) {
21995 ST->isUnindexed() &&
ST->isSimple() &&
22006 if (
SDValue NewST = replaceStoreOfInsertLoad(ST))
22010 if (
StoreSDNode *ST1 = dyn_cast<StoreSDNode>(Chain)) {
22011 if (
ST->isUnindexed() &&
ST->isSimple() &&
22012 ST1->isUnindexed() && ST1->isSimple()) {
22014 ST1->getValue() ==
Value &&
ST->getMemoryVT() == ST1->getMemoryVT() &&
22015 ST->getAddressSpace() == ST1->getAddressSpace()) {
22022 !ST1->getBasePtr().isUndef() &&
22023 ST->getAddressSpace() == ST1->getAddressSpace()) {
22028 if (
ST->getMemoryVT().isScalableVector() ||
22029 ST1->getMemoryVT().isScalableVector()) {
22030 if (ST1->getBasePtr() ==
Ptr &&
22032 ST->getMemoryVT().getStoreSize())) {
22033 CombineTo(ST1, ST1->getChain());
22043 if (STBase.contains(DAG,
ST->getMemoryVT().getFixedSizeInBits(),
22045 ST1->getMemoryVT().getFixedSizeInBits())) {
22046 CombineTo(ST1, ST1->getChain());
22060 ST->getMemoryVT(), LegalOperations)) {
22062 Ptr,
ST->getMemoryVT(),
ST->getMemOperand());
22073 bool Changed = mergeConsecutiveStores(ST);
22074 if (!Changed)
break;
22083 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
22091 if (isa<ConstantFPSDNode>(
ST->getValue())) {
22092 if (
SDValue NewSt = replaceStoreOfFPConstant(ST))
22099 return ReduceLoadOpStoreWidth(
N);
22103 const auto *LifetimeEnd = cast<LifetimeSDNode>(
N);
22104 if (!LifetimeEnd->hasOffset())
22108 LifetimeEnd->getOffset(),
false);
22112 while (!Chains.
empty()) {
22131 if (!
ST->isSimple() ||
ST->isIndexed())
22133 const TypeSize StoreSize =
ST->getMemoryVT().getStoreSize();
22141 if (LifetimeEndBase.contains(DAG, LifetimeEnd->getSize() * 8, StoreBase,
22144 dbgs() <<
"\nwithin LIFETIME_END of : ";
22145 LifetimeEndBase.dump();
dbgs() <<
"\n");
22146 CombineTo(ST,
ST->getChain());
22189 if (!
ST->isSimple())
22222 !
Lo.getOperand(0).getValueType().isScalarInteger() ||
22223 Lo.getOperand(0).getValueSizeInBits() > HalfValBitSize ||
22225 !
Hi.getOperand(0).getValueType().isScalarInteger() ||
22226 Hi.getOperand(0).getValueSizeInBits() > HalfValBitSize)
22232 ?
Lo.getOperand(0).getValueType()
22233 :
Lo.getValueType();
22235 ?
Hi.getOperand(0).getValueType()
22236 :
Hi.getValueType();
22253 ST->getOriginalAlign(), MMOFlags, AAInfo);
22258 St0,
DL,
Hi,
Ptr,
ST->getPointerInfo().getWithOffset(HalfValBitSize / 8),
22259 ST->getOriginalAlign(), MMOFlags, AAInfo);
22270 unsigned InsIndex) {
22279 int ElementOffset = -1;
22288 while (!ArgWorkList.
empty()) {
22291 std::tie(ArgOffset, ArgVal) = ArgWorkList.
pop_back_val();
22293 if (ArgVal == InsertVal0) {
22294 ElementOffset = ArgOffset;
22300 int CurrentArgOffset =
22304 CurrentArgOffset -= Step;
22310 assert(CurrentArgOffset == ArgOffset);
22316 if (ElementOffset == -1) {
22317 if (!
Y.isUndef() || InsertVal0.
getValueType() !=
Y.getValueType())
22319 ElementOffset = Mask.size();
22323 NewMask.
assign(Mask.begin(), Mask.end());
22325 assert(NewMask[InsIndex] < (
int)(2 * Mask.size()) && NewMask[InsIndex] >= 0 &&
22326 "NewMask[InsIndex] is out of bound");
22335SDValue DAGCombiner::mergeInsertEltWithShuffle(
SDNode *
N,
unsigned InsIndex) {
22337 "Expected extract_vector_elt");
22338 SDValue InsertVal =
N->getOperand(1);
22341 auto *SVN = dyn_cast<ShuffleVectorSDNode>(Vec);
22354 return LegalShuffle;
22365SDValue DAGCombiner::combineInsertEltToShuffle(
SDNode *
N,
unsigned InsIndex) {
22367 "Expected extract_vector_elt");
22368 SDValue InsertVal =
N->getOperand(1);
22375 SDValue DestVec =
N->getOperand(0);
22381 if (NumSrcElts == 1)
22384 unsigned NumMaskVals = ExtendRatio * NumSrcElts;
22392 for (
unsigned i = 0; i != NumMaskVals; ++i) {
22393 if (i / NumSrcElts == InsIndex)
22394 Mask[i] = (i % NumSrcElts) + NumMaskVals;
22409 ConcatOps[0] = SubVec;
22415 AddToWorklist(PaddedSubV.
getNode());
22416 AddToWorklist(DestVecBC.
getNode());
22417 AddToWorklist(Shuf.
getNode());
22424SDValue DAGCombiner::combineInsertEltToLoad(
SDNode *
N,
unsigned InsIndex) {
22425 EVT VT =
N->getValueType(0);
22434 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(0));
22437 return InsIndex == P.index() || P.value() < 0 ||
22438 (InsIndex == 0 && P.value() == (int)P.index() - 1) ||
22439 (InsIndex == VT.getVectorNumElements() - 1 &&
22440 P.value() == (int)P.index() + 1);
22446 unsigned Extend = 0;
22450 Extend =
Scalar.getOpcode();
22454 auto *ScalarLoad = dyn_cast<LoadSDNode>(Scalar);
22464 auto *
VecLoad = dyn_cast<LoadSDNode>(Vec);
22468 int EltSize = ScalarLoad->getValueType(0).getScalarSizeInBits();
22469 if (EltSize == 0 || EltSize % 8 != 0 || !ScalarLoad->isSimple() ||
22472 ScalarLoad->getAddressSpace() !=
VecLoad->getAddressSpace())
22477 if (InsIndex == 0) {
22488 unsigned IsFast = 0;
22492 NewAlign,
VecLoad->getMemOperand()->getFlags(),
22504 InsIndex == 0 ? ScalarLoad->getPointerInfo()
22505 :
VecLoad->getPointerInfo().getWithOffset(EltSize / 8);
22508 ScalarLoad->getChain(),
Ptr, PtrInfo, NewAlign);
22521 auto *IndexC = dyn_cast<ConstantSDNode>(EltNo);
22548 unsigned Elt = IndexC->getZExtValue();
22551 if (NumElts == 1) {
22567 && isa<ConstantSDNode>(InVec.
getOperand(2))) {
22569 if (Elt < OtherElt) {
22573 AddToWorklist(NewOp.
getNode());
22579 if (
SDValue Shuf = mergeInsertEltWithShuffle(
N, Elt))
22582 if (
SDValue Shuf = combineInsertEltToShuffle(
N, Elt))
22585 if (
SDValue Shuf = combineInsertEltToLoad(
N, Elt))
22601 EVT EltVT = Elt.getValueType();
22602 MaxEltVT = MaxEltVT.
bitsGE(EltVT) ? MaxEltVT : EltVT;
22610 assert(Ops.
size() == NumElts &&
"Unexpected vector size");
22624 for (
SDValue CurVec = InVec; CurVec;) {
22626 if (CurVec.isUndef())
22627 return CanonicalizeBuildVector(Ops);
22631 for (
unsigned I = 0;
I != NumElts; ++
I)
22632 AddBuildVectorOp(Ops, CurVec.getOperand(
I),
I);
22633 return CanonicalizeBuildVector(Ops);
22638 AddBuildVectorOp(Ops, CurVec.getOperand(0), 0);
22639 return CanonicalizeBuildVector(Ops);
22644 if (
auto *CurIdx = dyn_cast<ConstantSDNode>(CurVec.getOperand(2)))
22645 if (CurIdx->getAPIntValue().ult(NumElts)) {
22646 unsigned Idx = CurIdx->getZExtValue();
22647 AddBuildVectorOp(Ops, CurVec.getOperand(1),
Idx);
22651 return CanonicalizeBuildVector(Ops);
22653 CurVec = CurVec->getOperand(0);
22661 auto *SVN = cast<ShuffleVectorSDNode>(CurVec);
22665 bool Merged =
true;
22674 Mask = std::move(NewMask);
22691 for (
unsigned I = 0;
I != NumElts; ++
I)
22704 for (
unsigned I = 0;
I != NumElts; ++
I)
22711 for (
unsigned I = 0;
I != NumElts; ++
I)
22715 return CanonicalizeBuildVector(Ops);
22722SDValue DAGCombiner::scalarizeExtractedVectorLoad(
SDNode *EVE,
EVT InVecVT,
22745 if (
auto *ConstEltNo = dyn_cast<ConstantSDNode>(EltNo)) {
22746 int Elt = ConstEltNo->getZExtValue();
22757 unsigned IsFast = 0;
22771 if (ResultVT.
bitsGT(VecEltVT)) {
22778 NewPtr, MPI, VecEltVT, Alignment,
22788 if (ResultVT.
bitsLT(VecEltVT))
22800 const SDLoc &
DL,
bool LegalTypes) {
22804 auto *IndexC = dyn_cast<ConstantSDNode>(Index);
22838 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();
23812 unsigned OneConstExtractIndex = ~0
u;
23815 unsigned NumExtracts = 0;
23817 for (
unsigned i = 0; i != NumElems; ++i) {
23827 UsesZeroVector =
true;
23837 SDValue ExtractedFromVec =
Op.getOperand(0);
23840 auto *ExtractIdx = dyn_cast<ConstantSDNode>(
Op.getOperand(1));
23844 if (ExtractIdx->getAsAPIntVal().uge(
23853 OneConstExtractIndex = ExtractIdx->getZExtValue();
23865 VectorMask[i] =
Idx;
23869 if (VecIn.
size() < 2)
23876 bool DidSplitVec =
false;
23877 if (VecIn.
size() == 2) {
23886 if (NumExtracts == 1 &&
23892 unsigned MaxIndex = 0;
23893 unsigned NearestPow2 = 0;
23898 for (
unsigned i = 0; i < NumElems; i++) {
23899 if (VectorMask[i] <= 0)
23901 unsigned Index =
N->getOperand(i).getConstantOperandVal(1);
23902 IndexVec[i] =
Index;
23903 MaxIndex = std::max(MaxIndex, Index);
23907 if (InVT.
isSimple() && NearestPow2 > 2 && MaxIndex < NearestPow2 &&
23908 NumElems * 2 < NearestPow2) {
23909 unsigned SplitSize = NearestPow2 / 2;
23922 DidSplitVec =
true;
23924 for (
unsigned i = 0; i < NumElems; i++) {
23925 if (VectorMask[i] <= 0)
23927 VectorMask[i] = (IndexVec[i] < SplitSize) ? 1 : 2;
23940 b.getValueType().getVectorNumElements();
23945 for (
int &SourceVectorIndex : VectorMask) {
23946 if (SourceVectorIndex <= 0)
23950 VecIn[SourceVectorIndex] == SortedVecIn[
Idx] &&
"Remapping failure");
23951 SourceVectorIndex =
Idx;
23954 VecIn = std::move(SortedVecIn);
23972 for (
unsigned In = 0, Len = (VecIn.
size() / 2); In < Len; ++In) {
23973 unsigned LeftIdx = 2 *
In + 1;
23974 SDValue VecLeft = VecIn[LeftIdx];
23976 (LeftIdx + 1) < VecIn.
size() ? VecIn[LeftIdx + 1] :
SDValue();
23978 if (
SDValue Shuffle = createBuildVecShuffle(
DL,
N, VectorMask, VecLeft,
23979 VecRight, LeftIdx, DidSplitVec))
23987 if (UsesZeroVector)
23992 if (Shuffles.
size() == 1)
23993 return Shuffles[0];
23996 for (
int &Vec : VectorMask)
23998 Vec = Shuffles.
size() - 1;
24000 Vec = (Vec - 1) / 2;
24014 if (Shuffles.
size() % 2)
24017 for (
unsigned CurSize = Shuffles.
size(); CurSize > 1; CurSize /= 2) {
24019 Shuffles[CurSize] = DAG.
getUNDEF(VT);
24022 for (
unsigned In = 0, Len = CurSize / 2;
In <
Len; ++
In) {
24029 L.use_empty() &&
L.getOperand(1).isUndef() &&
24030 L.getOperand(0).getValueType() ==
L.getValueType();
24031 if (IsLeftShuffle) {
24032 LMask = cast<ShuffleVectorSDNode>(
L.getNode())->getMask();
24033 L =
L.getOperand(0);
24038 R.use_empty() &&
R.getOperand(1).isUndef() &&
24039 R.getOperand(0).getValueType() ==
R.getValueType();
24040 if (IsRightShuffle) {
24041 RMask = cast<ShuffleVectorSDNode>(
R.getNode())->getMask();
24042 R =
R.getOperand(0);
24044 for (
unsigned I = 0;
I != NumElems; ++
I) {
24045 if (VectorMask[
I] ==
Left) {
24049 VectorMask[
I] =
In;
24050 }
else if (VectorMask[
I] ==
Right) {
24052 if (IsRightShuffle)
24053 Mask[
I] = RMask[
I] + NumElems;
24054 VectorMask[
I] =
In;
24061 return Shuffles[0];
24069 if (LegalOperations)
24072 EVT VT =
N->getValueType(0);
24074 bool FoundZeroExtend =
false;
24076 auto checkElem = [&](
SDValue Op) -> int64_t {
24077 unsigned Opc =
Op.getOpcode();
24082 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op.getOperand(0).getOperand(1)))
24083 return C->getZExtValue();
24091 int64_t
Offset = checkElem(Op0);
24095 unsigned NumElems =
N->getNumOperands();
24097 EVT InSVT =
In.getValueType().getScalarType();
24105 for (
unsigned i = 1; i != NumElems; ++i) {
24106 if ((
Offset + i) != checkElem(
N->getOperand(i)))
24124SDValue DAGCombiner::convertBuildVecZextToBuildVecWithZeros(
SDNode *
N) {
24133 EVT VT =
N->getValueType(0);
24134 EVT OpVT =
N->getOperand(0).getValueType();
24148 unsigned ActiveBits = 0;
24153 if (
auto *Cst = dyn_cast<ConstantSDNode>(
Op)) {
24154 unsigned OpActiveBits =
24155 Cst->getAPIntValue().trunc(EltBitwidth).getActiveBits();
24156 if (OpActiveBits == 0) {
24157 KnownZeroOps.setBit(
I.index());
24165 if (
I.index() != 0)
24171 unsigned CurrActiveBits =
24172 Op.getOperand(0).getValueSizeInBits().getFixedValue();
24173 assert(!ActiveBits &&
"Already encountered non-constant-zero operand?");
24174 ActiveBits = CurrActiveBits;
24176 if (2 * ActiveBits > EltBitwidth)
24181 if (ActiveBits == 0)
24186 EVT NewScalarIntVT, NewIntVT;
24187 std::optional<unsigned> Factor;
24192 assert(2 * ActiveBits <= EltBitwidth &&
24193 "We know that half or less bits of the element are active.");
24194 for (
unsigned Scale = EltBitwidth / ActiveBits; Scale >= 2; --Scale) {
24195 if (EltBitwidth % Scale != 0)
24197 unsigned ChunkBitwidth = EltBitwidth / Scale;
24198 assert(ChunkBitwidth >= ActiveBits &&
"As per starting point.");
24201 Scale *
N->getNumOperands());
24203 (LegalOperations &&
24221 assert(!
Op.isUndef() &&
"FIXME: after allowing UNDEF's, handle them here.");
24222 unsigned SrcOpIdx =
I.index();
24223 if (KnownZeroOps[SrcOpIdx]) {
24224 NewOps.
append(*Factor, ZeroOp);
24230 NewOps.
append(*Factor - 1, ZeroOp);
24239 EVT VT =
N->getValueType(0);
24253 if (!LegalOperations) {
24254 SDValue Splat = cast<BuildVectorSDNode>(
N)->getSplatValue();
24275 if (!LegalTypes && (
N->getNumOperands() > 1)) {
24280 if (
auto CNode = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
24285 int Offset = checkElem(Op0);
24286 for (
unsigned i = 0; i <
N->getNumOperands(); ++i) {
24287 if (
Offset + i != checkElem(
N->getOperand(i))) {
24297 ((
Offset %
N->getValueType(0).getVectorNumElements()) ==
24303 if (
SDValue V = convertBuildVecZextToZext(
N))
24306 if (
SDValue V = convertBuildVecZextToBuildVecWithZeros(
N))
24309 if (
SDValue V = reduceBuildVecExtToExtBuildVec(
N))
24312 if (
SDValue V = reduceBuildVecTruncToBitCast(
N))
24315 if (
SDValue V = reduceBuildVecToShuffle(
N))
24322 assert(!
V.isUndef() &&
"Splat of undef should have been handled earlier");
24331 EVT OpVT =
N->getOperand(0).getValueType();
24338 EVT VT =
N->getValueType(0);
24347 !
Op.getOperand(0).getValueType().isVector())
24356 EVT LastOpVT = Ops.
back().getValueType();
24358 AnyFPVT = LastOpVT;
24366 if (AnyFPVT !=
EVT()) {
24369 if (
Op.getValueType() == SVT)
24388 EVT VT =
N->getValueType(0);
24398 if (!FirstConcat) {
24399 SubVT =
Op.getOperand(0).getValueType();
24405 if (SubVT !=
Op.getOperand(0).getValueType())
24408 assert(FirstConcat &&
"Concat of all-undefs found");
24412 if (
Op.isUndef()) {
24416 ConcatOps.
append(
Op->op_begin(),
Op->op_end());
24426 EVT VT =
N->getValueType(0);
24427 EVT OpVT =
N->getOperand(0).getValueType();
24443 if (
Op.isUndef()) {
24444 Mask.append((
unsigned)NumOpElts, -1);
24453 int ExtIdx =
Op.getConstantOperandVal(1);
24462 Mask.append((
unsigned)NumOpElts, -1);
24473 if (0 == (NumExtElts % NumElts))
24474 ExtIdx /= (NumExtElts / NumElts);
24475 else if (0 == (NumElts % NumExtElts))
24476 ExtIdx *= (NumElts / NumExtElts);
24481 if (SV0.
isUndef() || SV0 == ExtVec) {
24483 for (
int i = 0; i != NumOpElts; ++i)
24484 Mask.push_back(i + ExtIdx);
24485 }
else if (SV1.
isUndef() || SV1 == ExtVec) {
24487 for (
int i = 0; i != NumOpElts; ++i)
24488 Mask.push_back(i + ExtIdx + NumElts);
24500 unsigned CastOpcode =
N->getOperand(0).getOpcode();
24501 switch (CastOpcode) {
24517 EVT SrcVT =
N->getOperand(0).getOperand(0).getValueType();
24525 if (
Op.getOpcode() != CastOpcode || !
Op.hasOneUse() ||
24526 Op.getOperand(0).getValueType() != SrcVT)
24534 EVT VT =
N->getValueType(0);
24539 switch (CastOpcode) {
24559 return DAG.
getNode(CastOpcode,
DL, VT, NewConcat);
24567 bool LegalOperations) {
24568 EVT VT =
N->getValueType(0);
24569 EVT OpVT =
N->getOperand(0).getValueType();
24574 if (
N->getNumOperands() != 2)
24579 (LegalOperations &&
24590 if (
auto *CurSVN = dyn_cast<ShuffleVectorSDNode>(
Op);
24591 CurSVN && CurSVN->getOperand(1).
isUndef() &&
N->isOnlyUserOf(CurSVN) &&
24594 return !Op.isUndef() &&
24595 (Op.getNode() == CurSVN || is_contained(CurSVN->ops(), Op));
24618 std::iota(FirstShufOpIdentityMask.
begin(), FirstShufOpIdentityMask.
end(), 0);
24619 std::iota(SecondShufOpIdentityMask.
begin(), SecondShufOpIdentityMask.
end(),
24626 assert(!
Op.isUndef() &&
"Not expecting to concatenate UNDEF.");
24627 if (
Op.getNode() == SVN) {
24648 std::array<SDValue, 2> ShufOps;
24649 for (
auto I :
zip(SVN->
ops(), ShufOps)) {
24651 SDValue &NewShufOp = std::get<1>(
I);
24657 ShufOpParts[0] = ShufOp;
24667 if (
N->getNumOperands() == 1)
24668 return N->getOperand(0);
24671 EVT VT =
N->getValueType(0);
24677 [](
const SDValue &
Op) { return Op.isUndef(); })) {
24679 assert(
In.getValueType().isVector() &&
"Must concat vectors");
24689 !(LegalDAG &&
In.getValueType().isScalableVector())) {
24690 unsigned NumOps =
N->getNumOperands() *
In.getNumOperands();
24692 Ops.resize(NumOps, DAG.
getUNDEF(Ops[0].getValueType()));
24702 EVT SVT =
Scalar.getValueType().getVectorElementType();
24703 if (SVT ==
Scalar.getOperand(0).getValueType())
24708 if (!
Scalar.getValueType().isVector() &&
In.hasOneUse()) {
24727 if (VNTNumElms < 2)
24743 auto IsBuildVectorOrUndef = [](
const SDValue &
Op) {
24754 bool FoundMinVT =
false;
24757 EVT OpSVT =
Op.getOperand(0).getValueType();
24758 MinVT = (!FoundMinVT || OpSVT.
bitsLE(MinVT)) ? OpSVT : MinVT;
24761 assert(FoundMinVT &&
"Concat vector type mismatch");
24765 EVT OpVT =
Op.getValueType();
24774 Opnds.
append(
Op->op_begin(),
Op->op_begin() + NumElts);
24776 for (
unsigned i = 0; i != NumElts; ++i)
24784 "Concat vector type mismatch");
24807 N, DAG, TLI, LegalTypes, LegalOperations))
24817 unsigned PartNumElem =
24818 N->getOperand(0).getValueType().getVectorMinNumElements();
24820 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
24831 if (SingleSource.
getNode()) {
24832 if (
Op.getOperand(0) != SingleSource)
24835 SingleSource =
Op.getOperand(0);
24845 unsigned IdentityIndex = i * PartNumElem;
24846 if (
Op.getConstantOperandAPInt(1) != IdentityIndex)
24851 return SingleSource;
24860 V.getOperand(1).getValueType() == SubVT && V.getOperand(2) == Index) {
24861 return V.getOperand(1);
24863 auto *IndexC = dyn_cast<ConstantSDNode>(Index);
24865 V.getOperand(0).getValueType() == SubVT &&
24868 return V.getOperand(SubIdx);
24875 bool LegalOperations) {
24878 unsigned BinOpcode = BinOp.
getOpcode();
24884 if (VecVT != Bop0.
getValueType() || VecVT != Bop1.getValueType())
24898 if (!Sub0 || !Sub1)
24904 return DAG.
getNode(BinOpcode,
SDLoc(Extract), SubVT, Sub0, Sub1,
24911 bool LegalOperations) {
24919 auto *ExtractIndexC = dyn_cast<ConstantSDNode>(Extract->
getOperand(1));
24920 if (!ExtractIndexC)
24936 if (
C &&
C->getValueAPF().isNegZero())
24949 unsigned ExtractIndex = ExtractIndexC->getZExtValue();
24951 "Extract index is not a multiple of the vector length.");
24956 if (WideWidth % NarrowWidth != 0)
24961 unsigned NarrowingRatio = WideWidth / NarrowWidth;
24963 if (WideNumElts % NarrowingRatio != 0)
24968 WideNumElts / NarrowingRatio);
24995 if (NarrowingRatio != 2)
25010 return V.getOperand(ConcatOpNum);
25016 if (SubVecL || SubVecR) {
25047 auto *Ld = dyn_cast<LoadSDNode>(Extract->
getOperand(0));
25067 assert(Index % NumElts == 0 &&
"The extract subvector index is not a "
25068 "multiple of the result's element count");
25087 if (
Offset.isScalable()) {
25110 bool LegalOperations) {
25112 "Must only be called on EXTRACT_SUBVECTOR's");
25117 EVT NarrowVT =
N->getValueType(0);
25123 auto *WideShuffleVector = dyn_cast<ShuffleVectorSDNode>(N0);
25124 if (!WideShuffleVector)
25128 if (!WideShuffleVector->hasOneUse())
25132 if (LegalOperations &&
25136 uint64_t FirstExtractedEltIdx =
N->getConstantOperandVal(1);
25138 assert((FirstExtractedEltIdx % NumEltsExtracted) == 0 &&
25139 "Extract index is not a multiple of the output vector length.");
25144 NewMask.
reserve(NumEltsExtracted);
25146 DemandedSubvectors;
25149 for (
int M : WideShuffleVector->getMask().slice(FirstExtractedEltIdx,
25150 NumEltsExtracted)) {
25151 assert((M >= -1) && (M < (2 * WideNumElts)) &&
25152 "Out-of-bounds shuffle mask?");
25161 int WideShufOpIdx = M / WideNumElts;
25163 int OpEltIdx = M % WideNumElts;
25165 assert((OpEltIdx + WideShufOpIdx * WideNumElts) == M &&
25166 "Shuffle mask vector decomposition failure.");
25169 int OpSubvecIdx = OpEltIdx / NumEltsExtracted;
25171 int OpEltIdxInSubvec = OpEltIdx % NumEltsExtracted;
25173 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted) == OpEltIdx &&
25174 "Shuffle mask subvector decomposition failure.");
25176 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted +
25177 WideShufOpIdx * WideNumElts) == M &&
25178 "Shuffle mask full decomposition failure.");
25180 SDValue Op = WideShuffleVector->getOperand(WideShufOpIdx);
25182 if (
Op.isUndef()) {
25188 const std::pair<SDValue, int> DemandedSubvector =
25189 std::make_pair(
Op, OpSubvecIdx);
25191 if (DemandedSubvectors.insert(DemandedSubvector)) {
25192 if (DemandedSubvectors.size() > 2)
25195 int Index = NumEltsExtracted * OpSubvecIdx;
25203 getFirstIndexOf(DemandedSubvectors.getArrayRef(), DemandedSubvector);
25204 assert((NewOpIdx == 0 || NewOpIdx == 1) &&
"Unexpected operand index.");
25206 int AdjM = OpEltIdxInSubvec + NewOpIdx * NumEltsExtracted;
25209 assert(NewMask.
size() == (
unsigned)NumEltsExtracted &&
"Produced bad mask.");
25210 assert(DemandedSubvectors.size() <= 2 &&
25211 "Should have ended up demanding at most two subvectors.");
25214 if (DemandedSubvectors.empty())
25220 any_of(NewMask, [](
int M) {
return M < 0; }))
25221 for (
auto &DemandedSubvector : DemandedSubvectors)
25222 if (DemandedSubvector.second != 0)
25236 for (
const std::pair<SDValue /*Op*/, int /*SubvectorIndex*/>
25237 &DemandedSubvector : DemandedSubvectors) {
25239 int Index = NumEltsExtracted * DemandedSubvector.second;
25242 DemandedSubvector.first, IndexC));
25245 "Should end up with either one or two ops");
25248 if (NewOps.
size() == 1)
25255 EVT NVT =
N->getValueType(0);
25257 uint64_t ExtIdx =
N->getConstantOperandVal(1);
25272 V.getConstantOperandVal(1)) &&
25292 unsigned InsIdx =
V.getConstantOperandVal(2);
25294 if (InsIdx <= ExtIdx && (ExtIdx + NumSubElts) <= (InsIdx + NumInsElts) &&
25297 V.getValueType().isFixedLengthVector())
25305 V.getOperand(0).getValueType().isVector() &&
25310 unsigned DestNumElts =
V.getValueType().getVectorMinNumElements();
25311 if ((SrcNumElts % DestNumElts) == 0) {
25312 unsigned SrcDestRatio = SrcNumElts / DestNumElts;
25319 V.getOperand(0), NewIndex);
25323 if ((DestNumElts % SrcNumElts) == 0) {
25324 unsigned DestSrcRatio = DestNumElts / SrcNumElts;
25329 if ((ExtIdx % DestSrcRatio) == 0) {
25330 unsigned IndexValScaled = ExtIdx / DestSrcRatio;
25337 V.getOperand(0), NewIndex);
25345 V.getOperand(0), NewIndex);
25355 EVT ConcatSrcVT =
V.getOperand(0).getValueType();
25357 "Concat and extract subvector do not change element type");
25358 assert((ExtIdx % ExtNumElts) == 0 &&
25359 "Extract index is not a multiple of the input vector length.");
25362 unsigned ConcatOpIdx = ExtIdx / ConcatSrcNumElts;
25368 return V.getOperand(ConcatOpIdx);
25376 ConcatSrcNumElts % ExtNumElts == 0) {
25377 unsigned NewExtIdx = ExtIdx - ConcatOpIdx * ConcatSrcNumElts;
25378 assert(NewExtIdx + ExtNumElts <= ConcatSrcNumElts &&
25379 "Trying to extract from >1 concat operand?");
25380 assert(NewExtIdx % ExtNumElts == 0 &&
25381 "Extract index is not a multiple of the input vector length.");
25384 V.getOperand(ConcatOpIdx), NewIndexC);
25396 EVT InVT =
V.getValueType();
25400 if (ExtractSize % EltSize == 0) {
25401 unsigned NumElems = ExtractSize / EltSize;
25404 NumElems == 1 ? EltVT
25412 if (NumElems == 1) {
25413 SDValue Src =
V->getOperand(IdxVal);
25414 if (EltVT != Src.getValueType())
25430 EVT SmallVT =
V.getOperand(1).getValueType();
25431 if (!NVT.
bitsEq(SmallVT))
25439 uint64_t InsIdx =
V.getConstantOperandVal(2);
25449 DAG.
getBitcast(
N->getOperand(0).getValueType(),
V.getOperand(0)),
25479 unsigned HalfNumElts = NumElts / 2;
25482 for (
unsigned i = 0; i != NumElts; ++i) {
25486 if ((Mask[i] % NumElts) >= HalfNumElts)
25488 int M = Mask[i] < (int)NumElts ? Mask[i] : Mask[i] - (
int)HalfNumElts;
25489 if (i < HalfNumElts)
25492 Mask1[i - HalfNumElts] = M;
25515 EVT VT =
N->getValueType(0);
25526 unsigned NumConcats = NumElts / NumElemsPerConcat;
25528 auto IsUndefMaskElt = [](
int i) {
return i == -1; };
25533 if (NumElemsPerConcat * 2 == NumElts && N1.
isUndef() &&
25534 llvm::all_of(Mask.slice(NumElemsPerConcat, NumElemsPerConcat),
25538 Mask.slice(0, NumElemsPerConcat));
25545 for (
unsigned I = 0;
I != NumConcats; ++
I) {
25546 unsigned Begin =
I * NumElemsPerConcat;
25547 ArrayRef<int> SubMask = Mask.slice(Begin, NumElemsPerConcat);
25556 for (
int i = 0; i != (int)NumElemsPerConcat; ++i) {
25557 if (IsUndefMaskElt(SubMask[i]))
25559 if ((SubMask[i] % (
int)NumElemsPerConcat) != i)
25561 int EltOpIdx = SubMask[i] / NumElemsPerConcat;
25562 if (0 <= OpIdx && EltOpIdx != OpIdx)
25566 assert(0 <= OpIdx &&
"Unknown concat_vectors op");
25620 bool IsSplat =
false;
25621 auto *BV0 = dyn_cast<BuildVectorSDNode>(N0);
25622 auto *BV1 = dyn_cast<BuildVectorSDNode>(N1);
25624 if (
SDValue Splat0 = BV0->getSplatValue())
25625 IsSplat = (Splat0 == BV1->getSplatValue());
25629 for (
int M : SVN->
getMask()) {
25632 int Idx = M < (int)NumElts ? M : M - NumElts;
25633 SDValue &S = (M < (int)NumElts ? N0 : N1);
25635 Op = S.getOperand(
Idx);
25650 if (!IsSplat && !DuplicateOps.
insert(
Op).second)
25661 SVT = (SVT.
bitsLT(
Op.getValueType()) ?
Op.getValueType() : SVT);
25677 unsigned Opcode,
EVT VT, std::function<
bool(
unsigned)>
Match,
25679 bool LegalOperations) {
25684 return std::nullopt;
25692 for (
unsigned Scale = 2; Scale < NumElts; Scale *= 2) {
25694 if (NumElts % Scale != 0)
25708 return std::nullopt;
25717 bool LegalOperations) {
25727 Mask = SVN->
getMask()](
unsigned Scale) {
25728 for (
unsigned i = 0; i != NumElts; ++i) {
25731 if ((i % Scale) == 0 && Mask[i] == (int)(i / Scale))
25743 Opcode, VT, isAnyExtend, DAG, TLI,
true, LegalOperations);
25755 bool LegalOperations) {
25756 bool LegalTypes =
true;
25768 auto ForEachDecomposedIndice = [NumElts, &Mask](
auto Fn) {
25769 for (
int &Indice : Mask) {
25772 int OpIdx = (
unsigned)Indice < NumElts ? 0 : 1;
25773 int OpEltIdx = (
unsigned)Indice < NumElts ? Indice : Indice - NumElts;
25774 Fn(Indice, OpIdx, OpEltIdx);
25779 std::array<APInt, 2> OpsDemandedElts;
25780 for (
APInt &OpDemandedElts : OpsDemandedElts)
25782 ForEachDecomposedIndice(
25783 [&OpsDemandedElts](
int &Indice,
int OpIdx,
int OpEltIdx) {
25784 OpsDemandedElts[OpIdx].setBit(OpEltIdx);
25788 std::array<APInt, 2> OpsKnownZeroElts;
25789 for (
auto I :
zip(SVN->
ops(), OpsDemandedElts, OpsKnownZeroElts))
25797 bool HadZeroableElts =
false;
25798 ForEachDecomposedIndice([&OpsKnownZeroElts, &HadZeroableElts](
25799 int &Indice,
int OpIdx,
int OpEltIdx) {
25800 if (OpsKnownZeroElts[OpIdx][OpEltIdx]) {
25802 HadZeroableElts =
true;
25810 if (!HadZeroableElts)
25818 Mask.size() % ScaledMask.
size() == 0 &&
"Unexpected mask widening.");
25819 int Prescale = Mask.size() / ScaledMask.
size();
25821 NumElts = ScaledMask.
size();
25822 EltSizeInBits *= Prescale;
25834 auto isZeroExtend = [NumElts, &ScaledMask](
unsigned Scale) {
25835 assert(Scale >= 2 && Scale <= NumElts && NumElts % Scale == 0 &&
25836 "Unexpected mask scaling factor.");
25838 for (
unsigned SrcElt = 0, NumSrcElts = NumElts / Scale;
25839 SrcElt != NumSrcElts; ++SrcElt) {
25842 assert(MaskChunk.
size() == Scale &&
"Unexpected mask size.");
25843 Mask = Mask.drop_front(MaskChunk.
size());
25846 if (
int FirstIndice = MaskChunk[0]; (
unsigned)FirstIndice != SrcElt)
25851 [](
int Indice) { return Indice == -2; }))
25854 assert(Mask.empty() &&
"Did not process the whole mask?");
25859 for (
bool Commuted : {
false,
true}) {
25864 Opcode, PrescaledVT, isZeroExtend, DAG, TLI, LegalTypes,
25900 if (ExtDstSizeInBits % ExtSrcSizeInBits != 0)
25902 unsigned ExtScale = ExtDstSizeInBits / ExtSrcSizeInBits;
25907 auto isTruncate = [&Mask, &NumElts](
unsigned Scale) {
25908 for (
unsigned i = 0; i != NumElts; ++i) {
25911 if ((i * Scale) < NumElts && Mask[i] == (int)(i * Scale))
25921 if (EltSizeInBits != ExtSrcSizeInBits)
25926 if (isTruncate(ExtScale))
25949 APInt DemandedElts(NumElts, 0);
25953 assert((
unsigned)
Idx < NumElts &&
"Out-of-bounds shuffle indice?");
25956 assert(DemandedElts.
popcount() > 1 &&
"Is a splat shuffle already?");
25961 std::optional<unsigned> MinNonUndefIdx;
25963 if (
Idx < 0 || UndefElts[
Idx])
25965 MinNonUndefIdx = std::min<unsigned>(
Idx, MinNonUndefIdx.value_or(~0U));
25967 if (!MinNonUndefIdx)
25969 assert(*MinNonUndefIdx < NumElts &&
"Expected valid element index.");
25971 for (
int &
Idx : SplatMask) {
25976 Idx = UndefElts[
Idx] ? -1 : *MinNonUndefIdx;
25978 assert(SplatMask != Shuf->
getMask() &&
"Expected mask to change!");
25996 assert(ShufMask.
size() == SplatMask.
size() &&
"Mask length mismatch");
26014 auto CanSimplifyToExistingSplat = [](
ArrayRef<int> UserMask,
26016 for (
unsigned i = 0, e = UserMask.
size(); i != e; ++i)
26017 if (UserMask[i] != -1 && SplatMask[i] == -1 &&
26018 SplatMask[UserMask[i]] != -1)
26022 if (CanSimplifyToExistingSplat(ShufMask, SplatMask))
26028 for (
int Idx : ShufMask)
26041 bool LegalOperations) {
26058 if (VTLanes <= InLanes || VTLanes % InLanes != 0 ||
26059 (LegalOperations &&
26062 int Factor = VTLanes / InLanes;
26089 auto *InnerShuf = dyn_cast<ShuffleVectorSDNode>(OuterShuf->
getOperand(0));
26090 if (!InnerShuf || !InnerShuf->getOperand(1).isUndef())
26095 unsigned NumElts = OuterMask.
size();
26096 assert(NumElts == InnerMask.
size() &&
"Mask length mismatch");
26098 int SplatIndex = -1;
26099 for (
unsigned i = 0; i != NumElts; ++i) {
26101 int OuterMaskElt = OuterMask[i];
26102 if (OuterMaskElt == -1)
26106 int InnerMaskElt = InnerMask[OuterMaskElt];
26107 if (InnerMaskElt == -1)
26111 if (SplatIndex == -1)
26112 SplatIndex = InnerMaskElt;
26115 if (SplatIndex != InnerMaskElt)
26118 CombinedMask[i] = InnerMaskElt;
26120 assert((
all_of(CombinedMask, [](
int M) {
return M == -1; }) ||
26122 "Expected a splat mask");
26126 assert(VT == InnerShuf->getValueType(0) &&
"Expected matching shuffle types");
26131 InnerShuf->getOperand(1), CombinedMask);
26139 int MaskSize = Mask.size();
26140 int EltFromOp0 = -1;
26145 for (
int i = 0; i != MaskSize; ++i) {
26146 if (Mask[i] >= 0 && Mask[i] < MaskSize) {
26148 if (EltFromOp0 != -1)
26151 }
else if (Mask[i] != i + MaskSize) {
26171 if (ShufOp0Index == -1) {
26175 if (ShufOp0Index == -1)
26179 Mask = CommutedMask;
26187 assert(Mask[ShufOp0Index] >= 0 && Mask[ShufOp0Index] < (
int)Mask.size() &&
26188 "Shuffle mask value must be from operand 0");
26206 Op1, Elt, NewInsIndex);
26218 auto *Shuf0 = dyn_cast<ShuffleVectorSDNode>(Shuf->
getOperand(0));
26224 for (
int i = 0, e = (
int)Mask.size(); i != e; ++i) {
26228 assert(Mask[i] >= 0 && Mask[i] < e &&
"Unexpected shuffle mask value");
26232 if (Mask0[Mask[i]] != Mask0[i])
26241 EVT VT =
N->getValueType(0);
26266 bool Changed =
false;
26268 for (
unsigned i = 0; i != NumElts; ++i) {
26270 if (
Idx >= (
int)NumElts) {
26319 if (
auto *
Idx = dyn_cast<ConstantSDNode>(N0.
getOperand(2)))
26320 if (
Idx->getAPIntValue() == SplatIndex)
26346 SDValue ConvInput =
V->getOperand(0);
26353 assert(
V->getNumOperands() == NumElts &&
26354 "BUILD_VECTOR has wrong number of operands");
26356 bool AllSame =
true;
26357 for (
unsigned i = 0; i != NumElts; ++i) {
26358 if (!
V->getOperand(i).isUndef()) {
26359 Base =
V->getOperand(i);
26364 if (!
Base.getNode())
26366 for (
unsigned i = 0; i != NumElts; ++i) {
26367 if (
V->getOperand(i) !=
Base) {
26377 SDValue Splatted =
V->getOperand(SplatIndex);
26383 if (
V->getValueType(0) != VT)
26422 int HalfNumElts = (int)NumElts / 2;
26424 for (
unsigned i = 0; i != NumElts; ++i) {
26426 if (
Idx >= HalfNumElts) {
26427 assert(
Idx < (
int)NumElts &&
"Shuffle mask chooses undef op");
26428 Idx -= HalfNumElts;
26449 EVT SubVT =
RHS.getOperand(0).getValueType();
26450 int NumSubVecs =
RHS.getNumOperands();
26452 assert((NumElts % NumSubElts) == 0 &&
"Subvector mismatch");
26457 if (
all_of(Mask, [NumElts](
int M) {
return M < (int)NumElts; }))
26463 for (
int SubVec = 0; SubVec != NumSubVecs; ++SubVec) {
26464 for (
int SubIdx = 0; SubIdx != (int)NumElts; SubIdx += NumSubElts) {
26466 std::iota(InsertionMask.begin(), InsertionMask.end(), 0);
26469 std::iota(InsertionMask.begin() + SubIdx,
26470 InsertionMask.begin() + SubIdx + NumSubElts,
26471 NumElts + (SubVec * NumSubElts));
26474 bool MatchingShuffle =
true;
26475 for (
int i = 0; i != (int)NumElts; ++i) {
26476 int ExpectIdx = InsertionMask[i];
26477 int ActualIdx =
Mask[i];
26478 if (0 <= ActualIdx && ExpectIdx != ActualIdx) {
26479 MatchingShuffle =
false;
26484 if (MatchingShuffle)
26486 RHS.getOperand(SubVec),
26494 if (
SDValue InsertN1 = ShuffleToInsert(N0, N1, Mask))
26499 if (
SDValue InsertN0 = ShuffleToInsert(N1, N0, CommuteMask))
26507 bool IsInLaneMask =
true;
26512 for (
int I = 0;
I != (int)NumElts; ++
I) {
26516 ClearMask[
I] =
M ==
I ?
I : (
I + NumElts);
26517 IsInLaneMask &= (
M ==
I) || (M == (
int)(
I + NumElts));
26519 APInt &Demanded =
M < (int)NumElts ? DemandedLHS : DemandedRHS;
26520 Demanded.
setBit(M % NumElts);
26524 if (!IsInLaneMask && (!DemandedLHS.
isZero() || !DemandedRHS.
isZero()) &&
26539 for (
int I = 0;
I != (int)NumElts; ++
I)
26541 AndMask[
I] =
Mask[
I] ==
I ? AllOnesElt : ZeroElt;
26578 EVT ScaleVT = SVT.
bitsLT(InnerSVT) ? VT : InnerVT;
26596 for (
int M : OuterMask)
26597 NewMask.
push_back(M < 0 ? -1 : InnerMask[M]);
26628 auto MergeInnerShuffle =
26635 if (OtherSVN->isSplat())
26641 for (
unsigned i = 0; i != NumElts; ++i) {
26642 int Idx = SVN->getMaskElt(i);
26650 Idx = (
Idx < (int)NumElts) ? (
Idx + NumElts) : (
Idx - NumElts);
26653 if (
Idx < (
int)NumElts) {
26656 Idx = OtherSVN->getMaskElt(
Idx);
26662 CurrentVec = (
Idx < (int)NumElts) ? OtherSVN->
getOperand(0)
26671 Mask.push_back(-1);
26678 if (!SV0.getNode() || SV0 == CurrentVec) {
26685 if (!SV1.getNode() || SV1 == CurrentVec) {
26689 Mask.push_back(
Idx + NumElts);
26695 if (
auto *CurrentSVN = dyn_cast<ShuffleVectorSDNode>(CurrentVec)) {
26696 int InnerIdx = CurrentSVN->getMaskElt(
Idx);
26697 if (InnerIdx < 0) {
26698 Mask.push_back(-1);
26701 SDValue InnerVec = (InnerIdx < (int)NumElts)
26705 Mask.push_back(-1);
26708 InnerIdx %= NumElts;
26709 if (InnerVec == SV0) {
26710 Mask.push_back(InnerIdx);
26713 if (InnerVec == SV1) {
26714 Mask.push_back(InnerIdx + NumElts);
26733 if (TLI.isShuffleMaskLegal(Mask, VT))
26738 return TLI.isShuffleMaskLegal(Mask, VT);
26750 assert(N1->getOperand(0).getValueType() == VT &&
26751 "Shuffle types don't match");
26755 bool HasSameOp0 = N0 == SV0;
26756 bool IsSV1Undef = SV1.
isUndef();
26757 if (HasSameOp0 || IsSV1Undef || N0 == SV1)
26766 cast<ShuffleVectorSDNode>(N0)->isSplat() &&
26767 !cast<ShuffleVectorSDNode>(N1)->isSplat()) {
26778 for (
int i = 0; i != 2; ++i) {
26780 N->isOnlyUserOf(
N->getOperand(i).getNode())) {
26783 auto *OtherSV = cast<ShuffleVectorSDNode>(
N->getOperand(i));
26784 assert(OtherSV->getOperand(0).getValueType() == VT &&
26785 "Shuffle types don't match");
26789 if (MergeInnerShuffle(i != 0, SVN, OtherSV,
N->getOperand(1 - i), TLI,
26797 SV1 ? SV1 : DAG.
getUNDEF(VT), Mask);
26807 if (TLI.isBinOp(SrcOpcode) &&
N->isOnlyUserOf(N0.
getNode()) &&
26809 (SrcOpcode == N1.getOpcode() &&
N->isOnlyUserOf(N1.getNode())))) {
26827 SDValue InnerN = Commute ? N1 : N0;
26828 SDValue Op0 = LeftOp ? Op00 : Op01;
26829 SDValue Op1 = LeftOp ? Op10 : Op11;
26834 auto *SVN0 = dyn_cast<ShuffleVectorSDNode>(Op0);
26836 MergeInnerShuffle(Commute, SVN, SVN0, Op1, TLI, SV0, SV1,
26838 (
llvm::any_of(SVN0->getMask(), [](
int M) { return M < 0; }) ||
26844 bool MergedLeft =
false;
26847 if (CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
false) ||
26848 CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
true)) {
26851 LeftMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
26852 LeftSV0 = Op00, LeftSV1 = Op10;
26855 bool MergedRight =
false;
26858 if (CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
false) ||
26859 CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
true)) {
26860 MergedRight =
true;
26862 RightMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
26863 RightSV0 = Op01, RightSV1 = Op11;
26866 if (MergedLeft || MergedRight) {
26869 VT,
DL, LeftSV0 ? LeftSV0 : DAG.
getUNDEF(VT),
26870 LeftSV1 ? LeftSV1 : DAG.
getUNDEF(VT), LeftMask);
26872 VT,
DL, RightSV0 ? RightSV0 : DAG.
getUNDEF(VT),
26873 RightSV1 ? RightSV1 : DAG.
getUNDEF(VT), RightMask);
26874 return DAG.
getNode(SrcOpcode,
DL, VT, LHS, RHS);
26895 EVT VT =
N->getValueType(0);
26905 unsigned Opcode =
Scalar.getOpcode();
26907 if (
Scalar.hasOneUse() &&
Scalar->getNumValues() == 1 &&
26908 TLI.isBinOp(Opcode) &&
Scalar.getValueType() == VecEltVT &&
26909 Scalar.getOperand(0).getValueType() == VecEltVT &&
26910 Scalar.getOperand(1).getValueType() == VecEltVT &&
26911 Scalar->isOnlyUserOf(
Scalar.getOperand(0).getNode()) &&
26912 Scalar->isOnlyUserOf(
Scalar.getOperand(1).getNode()) &&
26917 for (
int i : {0, 1}) {
26921 auto *
C = dyn_cast<ConstantSDNode>(
Scalar.getOperand(i ? 0 : 1));
26928 if (TLI.isShuffleMaskLegal(ShufMask, VT)) {
26943 !
Scalar.getOperand(0).getValueType().isFixedLengthVector())
26947 if (VecEltVT !=
Scalar.getValueType() &&
26953 auto *ExtIndexC = dyn_cast<ConstantSDNode>(
Scalar.getOperand(1));
26961 if (VecEltVT == SrcVT.
getScalarType() && VTNumElts <= SrcNumElts) {
26964 Mask[0] = ExtIndexC->getZExtValue();
26965 SDValue LegalShuffle = TLI.buildLegalVectorShuffle(
26972 return LegalShuffle;
26975 if (VTNumElts != SrcNumElts) {
26988 EVT VT =
N->getValueType(0);
26992 uint64_t InsIdx =
N->getConstantOperandVal(2);
27092 if ((N0.
isUndef() || N0SrcSVT == N1SrcSVT) &&
27104 }
else if ((N1SrcSVT.
getSizeInBits() % EltSizeInBits) == 0) {
27127 if (InsIdx < OtherIdx) {
27131 AddToWorklist(NewOp.
getNode());
27145 Ops[InsIdx / Factor] = N1;
27167 auto Op =
N->getOpcode();
27169 "opcode should be FP16_TO_FP or BF16_TO_FP.");
27185 N->getValueType(0), {N0});
27201 return visitFP16_TO_FP(
N);
27207 unsigned Opcode =
N->getOpcode();
27225 if (!TLI.isOperationLegalOrCustom(Opcode, VT) &&
27226 TLI.isOperationLegalOrCustom(NewOpcode, VT) &&
27228 return DAG.
getNode(NewOpcode,
SDLoc(
N),
N->getValueType(0), N0);
27241 return DAG.
getNode(Opcode,
SDLoc(
N),
N->getValueType(0), Subvec);
27264 if (
SDValue Fused = visitFSUBForFMACombine<VPMatchContext>(
N)) {
27265 AddToWorklist(Fused.getNode());
27273 if (
N->getOpcode() == ISD::VP_GATHER)
27274 if (
SDValue SD = visitVPGATHER(
N))
27277 if (
N->getOpcode() == ISD::VP_SCATTER)
27278 if (
SDValue SD = visitVPSCATTER(
N))
27281 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_LOAD)
27282 if (
SDValue SD = visitVP_STRIDED_LOAD(
N))
27285 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_STORE)
27286 if (
SDValue SD = visitVP_STRIDED_STORE(
N))
27292 bool AreAllEltsDisabled =
false;
27296 AreAllEltsDisabled |=
27300 if (!AreAllEltsDisabled) {
27301 switch (
N->getOpcode()) {
27303 return visitVP_FADD(
N);
27305 return visitVP_FSUB(
N);
27307 return visitFMA<VPMatchContext>(
N);
27308 case ISD::VP_SELECT:
27309 return visitVP_SELECT(
N);
27311 return visitMUL<VPMatchContext>(
N);
27313 return foldSubCtlzNot<VPMatchContext>(
N, DAG);
27322 return DAG.
getUNDEF(
N->getValueType(0));
27326 if (
const auto *MemSD = dyn_cast<MemSDNode>(
N)) {
27327 if (MemSD->writeMem())
27328 return MemSD->getChain();
27329 return CombineTo(
N, DAG.
getUNDEF(
N->getValueType(0)), MemSD->getChain());
27334 return N->getOperand(0);
27342 EVT MemVT = cast<FPStateAccessSDNode>(
N)->getMemoryVT();
27347 for (
auto *U :
Ptr->users()) {
27350 if (
auto *Ld = dyn_cast<LoadSDNode>(U)) {
27351 if (LdNode && LdNode != Ld)
27366 if (
U.getResNo() == 0) {
27367 if (
auto *St = dyn_cast<StoreSDNode>(
U.getUser())) {
27385 CombineTo(StNode, Res,
false);
27392 EVT MemVT = cast<FPStateAccessSDNode>(
N)->getMemoryVT();
27396 for (
auto *U :
Ptr->users()) {
27399 if (
auto *St = dyn_cast<StoreSDNode>(U)) {
27400 if (StNode && StNode != St)
27415 auto *LdNode = dyn_cast<LoadSDNode>(StValue);
27436 EVT VT =
N->getValueType(0);
27443 if (LegalOperations)
27449 EVT RVT =
RHS.getValueType();
27450 unsigned NumElts =
RHS.getNumOperands();
27455 auto BuildClearMask = [&](
int Split) {
27456 int NumSubElts = NumElts *
Split;
27460 for (
int i = 0; i != NumSubElts; ++i) {
27461 int EltIdx = i /
Split;
27462 int SubIdx = i %
Split;
27472 if (
auto *Cst = dyn_cast<ConstantSDNode>(Elt))
27473 Bits = Cst->getAPIntValue();
27474 else if (
auto *CstFP = dyn_cast<ConstantFPSDNode>(Elt))
27481 Bits =
Bits.extractBits(NumSubBits, (Split - SubIdx - 1) * NumSubBits);
27483 Bits =
Bits.extractBits(NumSubBits, SubIdx * NumSubBits);
27485 if (
Bits.isAllOnes())
27487 else if (Bits == 0)
27496 if (!TLI.isVectorClearMaskLegal(Indices, ClearVT))
27510 for (
int Split = 1;
Split <= MaxSplit; ++
Split)
27512 if (
SDValue S = BuildClearMask(Split))
27521 const SDLoc &
DL,
bool LegalTypes) {
27524 unsigned Opcode =
N->getOpcode();
27525 EVT VT =
N->getValueType(0);
27532 int Index0, Index1;
27539 if (!Src0 || !Src1 || Index0 != Index1 ||
27566 for (
auto [
X,
Y] :
zip(EltsX, EltsY))
27582 EVT VT =
N->getValueType(0);
27583 assert(VT.
isVector() &&
"SimplifyVCastOp only works on vectors!");
27585 unsigned Opcode =
N->getOpcode();
27615 EVT VT =
N->getValueType(0);
27616 assert(VT.
isVector() &&
"SimplifyVBinOp only works on vectors!");
27620 unsigned Opcode =
N->getOpcode();
27631 auto *Shuf0 = dyn_cast<ShuffleVectorSDNode>(LHS);
27632 auto *Shuf1 = dyn_cast<ShuffleVectorSDNode>(RHS);
27633 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
27634 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
27637 RHS.getOperand(0), Flags);
27649 Shuf0->hasOneUse() && Shuf0->getOperand(1).isUndef() &&
27658 Shuf1->hasOneUse() && Shuf1->getOperand(1).isUndef() &&
27674 LHS.getOperand(2) ==
RHS.getOperand(2) &&
27679 EVT NarrowVT =
X.getValueType();
27680 if (NarrowVT ==
Y.getValueType() &&
27682 LegalOperations)) {
27695 return Op.isUndef() ||
27696 ISD::isBuildVectorOfConstantSDNodes(Op.getNode());
27705 if (ConcatWithConstantOrUndef(LHS) && ConcatWithConstantOrUndef(RHS) &&
27707 EVT NarrowVT =
LHS.getOperand(0).getValueType();
27708 if (NarrowVT ==
RHS.getOperand(0).getValueType() &&
27710 unsigned NumOperands =
LHS.getNumOperands();
27712 for (
unsigned i = 0; i != NumOperands; ++i) {
27715 RHS.getOperand(i)));
27731 "First argument must be a SetCC node!");
27734 cast<CondCodeSDNode>(N0.
getOperand(2))->get());
27739 if (
SCC.getNode()) {
27746 SCC.getOperand(0),
SCC.getOperand(1),
27747 SCC.getOperand(4), Flags);
27748 AddToWorklist(
SETCC.getNode());
27750 SCC.getOperand(2),
SCC.getOperand(3));
27765bool DAGCombiner::SimplifySelectOps(
SDNode *TheSelect,
SDValue LHS,
27778 CC = cast<CondCodeSDNode>(TheSelect->
getOperand(4))->get();
27785 CC = cast<CondCodeSDNode>(
Cmp.getOperand(2))->get();
27786 CmpLHS =
Cmp.getOperand(0);
27790 if (Zero &&
Zero->isZero() &&
27794 CombineTo(TheSelect, Sqrt);
27804 if (
LHS.getOpcode() !=
RHS.getOpcode() ||
27817 if (
LHS.getOperand(0) !=
RHS.getOperand(0) ||
27861 Visited.
insert(TheSelect);
27940 CombineTo(TheSelect, Load);
27944 CombineTo(
LHS.getNode(),
Load.getValue(0),
Load.getValue(1));
27945 CombineTo(
RHS.getNode(),
Load.getValue(0),
Load.getValue(1));
27985 auto *N2C = dyn_cast<ConstantSDNode>(N2.
getNode());
27986 if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue() - 1)) == 0)) {
27987 unsigned ShCt = XType.
getSizeInBits() - N2C->getAPIntValue().logBase2() - 1;
27991 AddToWorklist(Shift.
getNode());
27993 if (XType.
bitsGT(AType)) {
27995 AddToWorklist(Shift.
getNode());
27999 Shift = DAG.
getNOT(
DL, Shift, AType);
28011 AddToWorklist(Shift.
getNode());
28013 if (XType.
bitsGT(AType)) {
28015 AddToWorklist(Shift.
getNode());
28019 Shift = DAG.
getNOT(
DL, Shift, AType);
28082 EVT VT =
N->getValueType(0);
28090 EVT IntVT =
Int.getValueType();
28104 SignMask = ~SignMask;
28110 SignMask = ~SignMask;
28115 AddToWorklist(
Int.getNode());
28123SDValue DAGCombiner::convertSelectOfFPConstantsToLoadOffset(
28131 auto *TV = dyn_cast<ConstantFPSDNode>(N2);
28132 auto *FV = dyn_cast<ConstantFPSDNode>(N3);
28139 TLI.
isFPImmLegal(TV->getValueAPF(), TV->getValueType(0), ForCodeSize) ||
28140 TLI.
isFPImmLegal(FV->getValueAPF(), FV->getValueType(0), ForCodeSize))
28145 if (!TV->hasOneUse() && !FV->hasOneUse())
28149 const_cast<ConstantFP*
>(TV->getConstantFPValue()) };
28157 Align Alignment = cast<ConstantPoolSDNode>(CPIdx)->getAlign();
28166 AddToWorklist(
Cond.getNode());
28168 AddToWorklist(CstOffset.
getNode());
28170 AddToWorklist(CPIdx.
getNode());
28180 bool NotExtCompare) {
28182 if (N2 == N3)
return N2;
28187 auto *N1C = dyn_cast<ConstantSDNode>(N1.
getNode());
28188 auto *N2C = dyn_cast<ConstantSDNode>(N2.
getNode());
28189 auto *N3C = dyn_cast<ConstantSDNode>(N3.
getNode());
28193 AddToWorklist(
SCC.getNode());
28194 if (
auto *SCCC = dyn_cast<ConstantSDNode>(SCC)) {
28197 return !(SCCC->isZero()) ? N2 : N3;
28202 convertSelectOfFPConstantsToLoadOffset(
DL, N0, N1, N2, N3,
CC))
28205 if (
SDValue V = foldSelectCCToShiftAnd(
DL, N0, N1, N2, N3,
CC))
28217 auto *ConstAndRHS = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
28218 if (ConstAndRHS && ConstAndRHS->getAPIntValue().popcount() == 1) {
28220 const APInt &AndMask = ConstAndRHS->getAPIntValue();
28238 bool Fold = N2C &&
isNullConstant(N3) && N2C->getAPIntValue().isPowerOf2();
28239 bool Swap = N3C &&
isNullConstant(N2) && N3C->getAPIntValue().isPowerOf2();
28241 if ((Fold || Swap) &&
28253 if (NotExtCompare && N2C->isOne())
28266 AddToWorklist(
SCC.getNode());
28267 AddToWorklist(Temp.
getNode());
28272 unsigned ShCt = N2C->getAPIntValue().logBase2();
28297 if (
auto *ValueOnZeroC = dyn_cast<ConstantSDNode>(ValueOnZero)) {
28319 if (!NotExtCompare && N1C && N2C && N3C &&
28320 N2C->getAPIntValue() == ~N3C->getAPIntValue() &&
28335 if (
SDValue ABD = foldSelectToABD(N0, N1, N2, N3,
CC,
DL))
28344 bool foldBooleans) {
28346 DagCombineInfo(DAG, Level,
false,
this);
28444 bool AssumeNonZero) {
28447 auto PeekThroughCastsAndTrunc = [](
SDValue V) {
28449 switch (V.getOpcode()) {
28452 V = V.getOperand(0);
28463 Op = PeekThroughCastsAndTrunc(
Op);
28469 if (
C->isZero() ||
C->isOpaque())
28472 if (
C->getAPIntValue().isPowerOf2()) {
28488 for (
const APInt &Pow2 : Pow2Constants)
28497 auto CastToVT = [&](
EVT NewVT,
SDValue ToCast) {
28498 ToCast = PeekThroughCastsAndTrunc(ToCast);
28499 EVT CurVT = ToCast.getValueType();
28500 if (NewVT == CurVT)
28512 if (AssumeNonZero ||
Op->getFlags().hasNoUnsignedWrap() ||
28515 Depth + 1, AssumeNonZero))
28517 CastToVT(VT,
Op.getOperand(1)));
28524 Depth + 1, AssumeNonZero))
28526 Depth + 1, AssumeNonZero))
28527 return DAG.
getSelect(
DL, VT,
Op.getOperand(0), LogX, LogY);
28542 return DAG.
getNode(
Op.getOpcode(),
DL, VT, LogX, LogY);
28551 bool KnownNonZero,
bool InexpensiveOnly,
28552 std::optional<EVT> OutVT) {
28553 EVT VT = OutVT ? *OutVT :
V.getValueType();
28554 SDValue InexpensiveLogBase2 =
28557 return InexpensiveLogBase2;
28579 EVT VT =
Op.getValueType();
28587 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
28594 AddToWorklist(Est.getNode());
28602 for (
int i = 0; i < Iterations; ++i) {
28605 if (i == Iterations - 1) {
28607 AddToWorklist(MulEst.
getNode());
28611 AddToWorklist(NewEst.
getNode());
28614 (i == Iterations - 1 ?
N : FPOne), NewEst, Flags);
28615 AddToWorklist(NewEst.
getNode());
28618 AddToWorklist(NewEst.
getNode());
28621 AddToWorklist(Est.getNode());
28626 AddToWorklist(Est.getNode());
28642 unsigned Iterations,
28654 for (
unsigned i = 0; i < Iterations; ++i) {
28674 unsigned Iterations,
28687 for (
unsigned i = 0; i < Iterations; ++i) {
28696 if (Reciprocal || (i + 1) < Iterations) {
28719 EVT VT =
Op.getValueType();
28727 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
28734 bool UseOneConstNR =
false;
28738 AddToWorklist(Est.
getNode());
28740 if (Iterations > 0)
28741 Est = UseOneConstNR
28742 ? buildSqrtNROneConst(
Op, Est, Iterations, Flags, Reciprocal)
28743 : buildSqrtNRTwoConst(
Op, Est, Iterations,
Flags, Reciprocal);
28763 return buildSqrtEstimateImpl(
Op, Flags,
true);
28767 return buildSqrtEstimateImpl(
Op, Flags,
false);
28771bool DAGCombiner::mayAlias(
SDNode *Op0,
SDNode *Op1)
const {
28773 struct MemUseCharacteristics {
28782 auto getCharacteristics = [](
SDNode *
N) -> MemUseCharacteristics {
28783 if (
const auto *LSN = dyn_cast<LSBaseSDNode>(
N)) {
28785 if (
auto *
C = dyn_cast<ConstantSDNode>(LSN->getOffset()))
28788 ? -1 *
C->getSExtValue()
28791 return {LSN->isVolatile(), LSN->isAtomic(),
28792 LSN->getBasePtr(),
Offset ,
28795 if (
const auto *LN = cast<LifetimeSDNode>(
N))
28799 (LN->hasOffset()) ? LN->getOffset() : 0,
28812 MemUseCharacteristics MUC0 = getCharacteristics(Op0),
28813 MUC1 = getCharacteristics(Op1);
28816 if (MUC0.BasePtr.getNode() && MUC0.BasePtr == MUC1.BasePtr &&
28817 MUC0.Offset == MUC1.Offset)
28821 if (MUC0.IsVolatile && MUC1.IsVolatile)
28826 if (MUC0.IsAtomic && MUC1.IsAtomic)
28829 if (MUC0.MMO && MUC1.MMO) {
28830 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
28831 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
28837 if ((MUC0.NumBytes.hasValue() && MUC0.NumBytes.isScalable() &&
28838 MUC0.Offset != 0) ||
28839 (MUC1.NumBytes.hasValue() && MUC1.NumBytes.isScalable() &&
28851 if (!MUC0.MMO || !MUC1.MMO)
28857 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
28858 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
28866 int64_t SrcValOffset0 = MUC0.MMO->getOffset();
28867 int64_t SrcValOffset1 = MUC1.MMO->getOffset();
28868 Align OrigAlignment0 = MUC0.MMO->getBaseAlign();
28869 Align OrigAlignment1 = MUC1.MMO->getBaseAlign();
28873 if (OrigAlignment0 == OrigAlignment1 && SrcValOffset0 != SrcValOffset1 &&
28879 int64_t OffAlign0 = SrcValOffset0 % OrigAlignment0.
value();
28880 int64_t OffAlign1 = SrcValOffset1 % OrigAlignment1.
value();
28884 if ((OffAlign0 +
static_cast<int64_t
>(
28886 (OffAlign1 +
static_cast<int64_t
>(
28900 if (
UseAA && AA && MUC0.MMO->getValue() && MUC1.MMO->getValue() &&
28903 (!Size0.
isScalable() || SrcValOffset0 == 0) &&
28904 (!Size1.
isScalable() || SrcValOffset1 == 0)) {
28906 int64_t MinOffset = std::min(SrcValOffset0, SrcValOffset1);
28929void DAGCombiner::GatherAllAliases(
SDNode *
N,
SDValue OriginalChain,
28936 const bool IsLoad = isa<LoadSDNode>(
N) && cast<LoadSDNode>(
N)->isSimple();
28940 unsigned Depth = 0;
28943 auto ImproveChain = [&](
SDValue &
C) ->
bool {
28944 switch (
C.getOpcode()) {
28953 bool IsOpLoad = isa<LoadSDNode>(
C.getNode()) &&
28954 cast<LSBaseSDNode>(
C.getNode())->isSimple();
28955 if ((IsLoad && IsOpLoad) || !
mayAlias(
N,
C.getNode())) {
28957 C =
C.getOperand(0);
28966 C =
C.getOperand(0);
28975 C =
C.getOperand(0);
28988 while (!Chains.
empty()) {
29022 if (ImproveChain(Chain)) {
29044 GatherAllAliases(
N, OldChain, Aliases);
29047 if (Aliases.
empty())
29051 if (Aliases.
size() == 1)
29071bool DAGCombiner::parallelizeChainedStores(
StoreSDNode *St) {
29088 if (!
BasePtr.getBase().getNode())
29092 if (
BasePtr.getBase().isUndef())
29110 if (Chain->getMemoryVT().isScalableVector())
29114 if (!
SDValue(Chain, 0)->hasOneUse())
29117 if (!Chain->isSimple() || Chain->isIndexed())
29126 int64_t
Length = (Chain->getMemoryVT().getSizeInBits() + 7) / 8;
29129 auto I = Intervals.find(
Offset);
29134 if (
I != Intervals.begin() && (--
I).stop() <=
Offset)
29143 if (ChainedStores.
empty())
29150 for (
unsigned I = ChainedStores.
size();
I;) {
29152 SDValue BetterChain = FindBetterChain(S, NewChain);
29156 ChainedStores[
I] = S;
29160 SDValue BetterChain = FindBetterChain(St, NewChain);
29175 auto hasImprovedChain = [&](
SDValue ST) ->
bool {
29176 return ST->getOperand(0) != NewChain;
29178 bool AddNewChain =
llvm::all_of(TFOps, hasImprovedChain);
29188 AddToWorklist(
Op.getNode());
29189 AddToWorklist(STChain);
29193bool DAGCombiner::findBetterNeighborChains(
StoreSDNode *St) {
29200 if (!
BasePtr.getBase().getNode())
29204 if (
BasePtr.getBase().isUndef())
29208 if (parallelizeChainedStores(St))
29213 if (St->
getChain() != BetterChain) {
29214 replaceStoreChain(St, BetterChain);
29224 DAGCombiner(*
this, AA, OptLevel).Run(Level);
static bool mayAlias(MachineInstr &MIa, SmallVectorImpl< MachineInstr * > &MemInsns, AliasAnalysis *AA)
static cl::opt< bool > UseAA("aarch64-use-aa", cl::init(true), cl::desc("Enable the use of AA during codegen."))
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
AMDGPU Register Bank Select
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static bool splitMergedValStore(StoreInst &SI, const DataLayout &DL, const TargetLowering &TLI)
For the instruction sequence of store below, F and I values are bundled together as an i64 value befo...
static unsigned bigEndianByteAt(const unsigned ByteWidth, const unsigned I)
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
static bool canFoldInAddressingMode(GLoadStore *MI, const TargetLowering &TLI, MachineRegisterInfo &MRI)
Return true if 'MI' is a load or a store that may be fold it's address operand into the load / store ...
static unsigned littleEndianByteAt(const unsigned ByteWidth, const unsigned I)
static bool isAnyConstantBuildVector(SDValue V, bool NoOpaques=false)
static cl::opt< bool > EnableShrinkLoadReplaceStoreWithStore("combiner-shrink-load-replace-store-with-store", cl::Hidden, cl::init(true), cl::desc("DAG combiner enable load/<replace bytes>/store with " "a narrower store"))
static bool ExtendUsesToFormExtLoad(EVT VT, SDNode *N, SDValue N0, unsigned ExtOpc, SmallVectorImpl< SDNode * > &ExtendNodes, const TargetLowering &TLI)
static cl::opt< unsigned > TokenFactorInlineLimit("combiner-tokenfactor-inline-limit", cl::Hidden, cl::init(2048), cl::desc("Limit the number of operands to inline for Token Factors"))
static SDValue tryToFoldExtOfLoad(SelectionDAG &DAG, DAGCombiner &Combiner, const TargetLowering &TLI, EVT VT, bool LegalOperations, SDNode *N, SDValue N0, ISD::LoadExtType ExtLoadType, ISD::NodeType ExtOpc, bool NonNegZExt=false)
static SDValue ConvertSelectToConcatVector(SDNode *N, SelectionDAG &DAG)
static SDNode * getBuildPairElt(SDNode *N, unsigned i)
static SDValue foldBitOrderCrossLogicOp(SDNode *N, SelectionDAG &DAG)
static SDValue tryToFoldExtendOfConstant(SDNode *N, const SDLoc &DL, const TargetLowering &TLI, SelectionDAG &DAG, bool LegalTypes)
Try to fold a sext/zext/aext dag node into a ConstantSDNode or a build_vector of constants.
static SDValue extractShiftForRotate(SelectionDAG &DAG, SDValue OppShift, SDValue ExtractFrom, SDValue &Mask, const SDLoc &DL)
Helper function for visitOR to extract the needed side of a rotate idiom from a shl/srl/mul/udiv.
static bool getCombineLoadStoreParts(SDNode *N, unsigned Inc, unsigned Dec, bool &IsLoad, bool &IsMasked, SDValue &Ptr, const TargetLowering &TLI)
bool refineUniformBase(SDValue &BasePtr, SDValue &Index, bool IndexIsScaled, SelectionDAG &DAG, const SDLoc &DL)
static SDValue scalarizeExtractedBinOp(SDNode *ExtElt, SelectionDAG &DAG, const SDLoc &DL, bool LegalTypes)
Transform a vector binary operation into a scalar binary operation by moving the math/logic after an ...
static bool isDivRemLibcallAvailable(SDNode *Node, bool isSigned, const TargetLowering &TLI)
Return true if divmod libcall is available.
static SDValue reduceBuildVecToShuffleWithZero(SDNode *BV, SelectionDAG &DAG)
static SDValue foldAddSubMasked1(bool IsAdd, SDValue N0, SDValue N1, SelectionDAG &DAG, const SDLoc &DL)
Given the operands of an add/sub operation, see if the 2nd operand is a masked 0/1 whose source opera...
static bool mergeEltWithShuffle(SDValue &X, SDValue &Y, ArrayRef< int > Mask, SmallVectorImpl< int > &NewMask, SDValue Elt, unsigned InsIndex)
static SDValue simplifyShuffleOfShuffle(ShuffleVectorSDNode *Shuf)
If we have a unary shuffle of a shuffle, see if it can be folded away completely.
static bool canSplitIdx(LoadSDNode *LD)
static SDValue ShrinkLoadReplaceStoreWithStore(const std::pair< unsigned, unsigned > &MaskInfo, SDValue IVal, StoreSDNode *St, DAGCombiner *DC)
Check to see if IVal is something that provides a value as specified by MaskInfo.
static cl::opt< bool > StressLoadSlicing("combiner-stress-load-slicing", cl::Hidden, cl::desc("Bypass the profitability model of load slicing"), cl::init(false))
Hidden option to stress test load slicing, i.e., when this option is enabled, load slicing bypasses m...
static cl::opt< bool > UseTBAA("combiner-use-tbaa", cl::Hidden, cl::init(true), cl::desc("Enable DAG combiner's use of TBAA"))
static void adjustCostForPairing(SmallVectorImpl< LoadedSlice > &LoadedSlices, LoadedSlice::Cost &GlobalLSCost)
Adjust the GlobalLSCost according to the target paring capabilities and the layout of the slices.
static SDValue narrowInsertExtractVectorBinOp(SDNode *Extract, SelectionDAG &DAG, bool LegalOperations)
static SDValue combineCarryDiamond(SelectionDAG &DAG, const TargetLowering &TLI, SDValue N0, SDValue N1, SDNode *N)
static SDValue foldExtendVectorInregToExtendOfSubvector(SDNode *N, const SDLoc &DL, const TargetLowering &TLI, SelectionDAG &DAG, bool LegalOperations)
static bool isCompatibleLoad(SDValue N, unsigned ExtOpcode)
Check if N satisfies: N is used once.
static SDValue widenCtPop(SDNode *Extend, SelectionDAG &DAG, const SDLoc &DL)
Given an extending node with a pop-count operand, if the target does not support a pop-count in the n...
static SDValue foldLogicTreeOfShifts(SDNode *N, SDValue LeftHand, SDValue RightHand, SelectionDAG &DAG)
Given a tree of logic operations with shape like (LOGIC (LOGIC (X, Y), LOGIC (Z, Y))) try to match an...
static SDValue partitionShuffleOfConcats(SDNode *N, SelectionDAG &DAG)
static SDValue narrowExtractedVectorBinOp(SDNode *Extract, SelectionDAG &DAG, bool LegalOperations)
If we are extracting a subvector produced by a wide binary operator try to use a narrow binary operat...
static SDValue takeInexpensiveLog2(SelectionDAG &DAG, const SDLoc &DL, EVT VT, SDValue Op, unsigned Depth, bool AssumeNonZero)
static SDValue combineSelectAsExtAnd(SDValue Cond, SDValue T, SDValue F, const SDLoc &DL, SelectionDAG &DAG)
static bool areUsedBitsDense(const APInt &UsedBits)
Check that all bits set in UsedBits form a dense region, i.e., UsedBits looks like 0....
static SDValue getInputChainForNode(SDNode *N)
Given a node, return its input chain if it has one, otherwise return a null sd operand.
static SDValue narrowExtractedVectorLoad(SDNode *Extract, SelectionDAG &DAG)
If we are extracting a subvector from a wide vector load, convert to a narrow load to eliminate the e...
static ElementCount numVectorEltsOrZero(EVT T)
static SDValue foldSelectWithIdentityConstant(SDNode *N, SelectionDAG &DAG, bool ShouldCommuteOperands)
This inverts a canonicalization in IR that replaces a variable select arm with an identity constant.
static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG)
static SDValue replaceShuffleOfInsert(ShuffleVectorSDNode *Shuf, SelectionDAG &DAG)
If a shuffle inserts exactly one element from a source vector operand into another vector operand and...
static SDValue tryToFoldExtOfExtload(SelectionDAG &DAG, DAGCombiner &Combiner, const TargetLowering &TLI, EVT VT, bool LegalOperations, SDNode *N, SDValue N0, ISD::LoadExtType ExtLoadType)
static SDValue foldAndToUsubsat(SDNode *N, SelectionDAG &DAG, const SDLoc &DL)
For targets that support usubsat, match a bit-hack form of that operation that ends in 'and' and conv...
static cl::opt< bool > CombinerGlobalAA("combiner-global-alias-analysis", cl::Hidden, cl::desc("Enable DAG combiner's use of IR alias analysis"))
static bool isConstantSplatVectorMaskForType(SDNode *N, EVT ScalarTy)
static SDValue formSplatFromShuffles(ShuffleVectorSDNode *OuterShuf, SelectionDAG &DAG)
Combine shuffle of shuffle of the form: shuf (shuf X, undef, InnerMask), undef, OuterMask --> splat X...
static bool isDivisorPowerOfTwo(SDValue Divisor)
static bool matchRotateHalf(const SelectionDAG &DAG, SDValue Op, SDValue &Shift, SDValue &Mask)
Match "(X shl/srl V1) & V2" where V2 may not be present.
static SDValue foldExtractSubvectorFromShuffleVector(SDNode *N, SelectionDAG &DAG, const TargetLowering &TLI, bool LegalOperations)
Given EXTRACT_SUBVECTOR(VECTOR_SHUFFLE(Op0, Op1, Mask)), try to produce VECTOR_SHUFFLE(EXTRACT_SUBVEC...
static SDValue combineConcatVectorOfExtracts(SDNode *N, SelectionDAG &DAG)
static bool hasNoInfs(const TargetOptions &Options, SDValue N)
static bool isLegalToCombineMinNumMaxNum(SelectionDAG &DAG, SDValue LHS, SDValue RHS, const SDNodeFlags Flags, const TargetLowering &TLI)
static SDValue combineShuffleOfBitcast(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const TargetLowering &TLI, bool LegalOperations)
static std::optional< EVT > canCombineShuffleToExtendVectorInreg(unsigned Opcode, EVT VT, std::function< bool(unsigned)> Match, SelectionDAG &DAG, const TargetLowering &TLI, bool LegalTypes, bool LegalOperations)
static SDValue PerformUMinFpToSatCombine(SDValue N0, SDValue N1, SDValue N2, SDValue N3, ISD::CondCode CC, SelectionDAG &DAG)
static SDValue combineShuffleToAnyExtendVectorInreg(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const TargetLowering &TLI, bool LegalOperations)
static SDValue foldAddSubOfSignBit(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
Try to fold a 'not' shifted sign-bit with add/sub with constant operand into a shift and add with a d...
static SDValue stripTruncAndExt(SDValue Value)
static SDValue combineUADDO_CARRYDiamond(DAGCombiner &Combiner, SelectionDAG &DAG, SDValue X, SDValue Carry0, SDValue Carry1, SDNode *N)
If we are facing some sort of diamond carry propagation pattern try to break it up to generate someth...
static SDValue foldShuffleOfConcatUndefs(ShuffleVectorSDNode *Shuf, SelectionDAG &DAG)
Try to convert a wide shuffle of concatenated vectors into 2 narrow shuffles followed by concatenatio...
static SDValue combineShuffleOfSplatVal(ShuffleVectorSDNode *Shuf, SelectionDAG &DAG)
static auto getFirstIndexOf(R &&Range, const T &Val)
static std::pair< unsigned, unsigned > CheckForMaskedLoad(SDValue V, SDValue Ptr, SDValue Chain)
Check to see if V is (and load (ptr), imm), where the load is having specific bytes cleared out.
static int getShuffleMaskIndexOfOneElementFromOp0IntoOp1(ArrayRef< int > Mask)
If the shuffle mask is taking exactly one element from the first vector operand and passing through a...
static bool shouldConvertSelectOfConstantsToMath(const SDValue &Cond, EVT VT, const TargetLowering &TLI)
static cl::opt< bool > EnableStoreMerging("combiner-store-merging", cl::Hidden, cl::init(true), cl::desc("DAG combiner enable merging multiple stores " "into a wider store"))
static bool isContractableFMUL(const TargetOptions &Options, SDValue N)
static cl::opt< bool > MaySplitLoadIndex("combiner-split-load-index", cl::Hidden, cl::init(true), cl::desc("DAG combiner may split indexing from loads"))
static bool areSlicesNextToEachOther(const LoadedSlice &First, const LoadedSlice &Second)
Check whether or not First and Second are next to each other in memory.
static SDValue stripConstantMask(const SelectionDAG &DAG, SDValue Op, SDValue &Mask)
static bool arebothOperandsNotSNan(SDValue Operand1, SDValue Operand2, SelectionDAG &DAG)
static bool isBSwapHWordPair(SDValue N, MutableArrayRef< SDNode * > Parts)
static SDValue foldFPToIntToFP(SDNode *N, const SDLoc &DL, SelectionDAG &DAG, const TargetLowering &TLI)
static bool CanCombineFCOPYSIGN_EXTEND_ROUND(EVT XTy, EVT YTy)
copysign(x, fp_extend(y)) -> copysign(x, y) copysign(x, fp_round(y)) -> copysign(x,...
static cl::opt< bool > ReduceLoadOpStoreWidthForceNarrowingProfitable("combiner-reduce-load-op-store-width-force-narrowing-profitable", cl::Hidden, cl::init(false), cl::desc("DAG combiner force override the narrowing profitable check when " "reducing the width of load/op/store sequences"))
static unsigned getMinMaxOpcodeForFP(SDValue Operand1, SDValue Operand2, ISD::CondCode CC, unsigned OrAndOpcode, SelectionDAG &DAG, bool isFMAXNUMFMINNUM_IEEE, bool isFMAXNUMFMINNUM)
static SDValue getTruncatedUSUBSAT(EVT DstVT, EVT SrcVT, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
static SDValue foldToSaturated(SDNode *N, EVT &VT, SDValue &Src, EVT &SrcVT, SDLoc &DL, const TargetLowering &TLI, SelectionDAG &DAG)
static SDValue FoldIntToFPToInt(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
static SDValue foldSubCtlzNot(SDNode *N, SelectionDAG &DAG)
static SDNode * getPostIndexedLoadStoreOp(SDNode *N, bool &IsLoad, bool &IsMasked, SDValue &Ptr, SDValue &BasePtr, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG, const TargetLowering &TLI)
static SDValue extractBooleanFlip(SDValue V, SelectionDAG &DAG, const TargetLowering &TLI, bool Force)
Flips a boolean if it is cheaper to compute.
static bool isTruncateOf(SelectionDAG &DAG, SDValue N, SDValue &Op, KnownBits &Known)
static SDValue tryToFoldExtOfMaskedLoad(SelectionDAG &DAG, const TargetLowering &TLI, EVT VT, bool LegalOperations, SDNode *N, SDValue N0, ISD::LoadExtType ExtLoadType, ISD::NodeType ExtOpc)
static SDValue getSubVectorSrc(SDValue V, SDValue Index, EVT SubVT)
static SDValue combineConcatVectorOfShuffleAndItsOperands(SDNode *N, SelectionDAG &DAG, const TargetLowering &TLI, bool LegalTypes, bool LegalOperations)
bool refineIndexType(SDValue &Index, ISD::MemIndexType &IndexType, EVT DataVT, SelectionDAG &DAG)
static cl::opt< bool > EnableVectorFCopySignExtendRound("combiner-vector-fcopysign-extend-round", cl::Hidden, cl::init(false), cl::desc("Enable merging extends and rounds into FCOPYSIGN on vector types"))
static SDValue combineMinNumMaxNumImpl(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode CC, const TargetLowering &TLI, SelectionDAG &DAG)
static SDValue combineShiftOfShiftedLogic(SDNode *Shift, SelectionDAG &DAG)
If we have a shift-by-constant of a bitwise logic op that itself has a shift-by-constant operand with...
static SDValue widenAbs(SDNode *Extend, SelectionDAG &DAG)
static void zeroExtendToMatch(APInt &LHS, APInt &RHS, unsigned Offset=0)
static SDValue combineShiftToMULH(SDNode *N, const SDLoc &DL, SelectionDAG &DAG, const TargetLowering &TLI)
static ConstantSDNode * getAsNonOpaqueConstant(SDValue N)
If N is a ConstantSDNode with isOpaque() == false return it casted to a ConstantSDNode pointer else n...
static bool arebothOperandsNotNan(SDValue Operand1, SDValue Operand2, SelectionDAG &DAG)
static SDValue detectUSatUPattern(SDValue In, EVT VT)
Detect patterns of truncation with unsigned saturation:
static SDValue PerformMinMaxFpToSatCombine(SDValue N0, SDValue N1, SDValue N2, SDValue N3, ISD::CondCode CC, SelectionDAG &DAG)
static bool matchRotateSub(SDValue Pos, SDValue Neg, unsigned EltSize, SelectionDAG &DAG, bool IsRotate)
static SDValue visitORCommutative(SelectionDAG &DAG, SDValue N0, SDValue N1, SDNode *N)
OR combines for which the commuted variant will be tried as well.
static SDValue detectSSatUPattern(SDValue In, EVT VT, SelectionDAG &DAG, const SDLoc &DL)
Detect patterns of truncation with unsigned saturation:
static SDValue combineShuffleToZeroExtendVectorInReg(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const TargetLowering &TLI, bool LegalOperations)
static cl::opt< bool > EnableReduceLoadOpStoreWidth("combiner-reduce-load-op-store-width", cl::Hidden, cl::init(true), cl::desc("DAG combiner enable reducing the width of load/op/store " "sequence"))
static bool shouldCombineToPostInc(SDNode *N, SDValue Ptr, SDNode *PtrUse, SDValue &BasePtr, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG, const TargetLowering &TLI)
static SDValue foldExtendedSignBitTest(SDNode *N, SelectionDAG &DAG, bool LegalOperations)
static SDValue combineConcatVectorOfCasts(SDNode *N, SelectionDAG &DAG)
static SDValue combineShiftAnd1ToBitTest(SDNode *And, SelectionDAG &DAG)
Try to replace shift/logic that tests if a bit is clear with mask + setcc.
static bool areBitwiseNotOfEachother(SDValue Op0, SDValue Op1)
static SDValue combineShuffleOfScalars(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const TargetLowering &TLI)
static SDValue combineConcatVectorOfScalars(SDNode *N, SelectionDAG &DAG)
static SDValue scalarizeBinOpOfSplats(SDNode *N, SelectionDAG &DAG, const SDLoc &DL, bool LegalTypes)
If a vector binop is performed on splat values, it may be profitable to extract, scalarize,...
static SDValue foldVSelectToSignBitSplatMask(SDNode *N, SelectionDAG &DAG)
static SDValue foldAddSubBoolOfMaskedVal(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
static SDValue combineConcatVectorOfConcatVectors(SDNode *N, SelectionDAG &DAG)
static SDValue tryToFoldExtOfAtomicLoad(SelectionDAG &DAG, const TargetLowering &TLI, EVT VT, SDValue N0, ISD::LoadExtType ExtLoadType)
static SDValue matchBSwapHWordOrAndAnd(const TargetLowering &TLI, SelectionDAG &DAG, SDNode *N, SDValue N0, SDValue N1, EVT VT)
static SDValue tryToFoldExtendSelectLoad(SDNode *N, const TargetLowering &TLI, SelectionDAG &DAG, const SDLoc &DL, CombineLevel Level)
Fold (sext (select c, load x, load y)) -> (select c, sextload x, sextload y) (zext (select c,...
static SDValue getAsCarry(const TargetLowering &TLI, SDValue V, bool ForceCarryReconstruction=false)
static SDValue foldSelectOfConstantsUsingSra(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
If a (v)select has a condition value that is a sign-bit test, try to smear the condition operand sign...
static unsigned getPPCf128HiElementSelector(const SelectionDAG &DAG)
static SDValue detectSSatSPattern(SDValue In, EVT VT)
Detect patterns of truncation with signed saturation: (truncate (smin (smax (x, signed_min_of_dest_ty...
static SDValue combineTruncationShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG)
static SDValue tryFoldToZero(const SDLoc &DL, const TargetLowering &TLI, EVT VT, SelectionDAG &DAG, bool LegalOperations)
static cl::opt< unsigned > StoreMergeDependenceLimit("combiner-store-merge-dependence-limit", cl::Hidden, cl::init(10), cl::desc("Limit the number of times for the same StoreNode and RootNode " "to bail out in store merging dependence check"))
static cl::opt< std::string > CombinerAAOnlyFunc("combiner-aa-only-func", cl::Hidden, cl::desc("Only use DAG-combiner alias analysis in this" " function"))
static SDValue foldLogicOfShifts(SDNode *N, SDValue LogicOp, SDValue ShiftOp, SelectionDAG &DAG)
Given a bitwise logic operation N with a matching bitwise logic operand, fold a pattern where 2 of th...
static bool isSlicingProfitable(SmallVectorImpl< LoadedSlice > &LoadedSlices, const APInt &UsedBits, bool ForCodeSize)
Check the profitability of all involved LoadedSlice.
static bool isBSwapHWordElement(SDValue N, MutableArrayRef< SDNode * > Parts)
Return true if the specified node is an element that makes up a 32-bit packed halfword byteswap.
static SDValue isSaturatingMinMax(SDValue N0, SDValue N1, SDValue N2, SDValue N3, ISD::CondCode CC, unsigned &BW, bool &Unsigned, SelectionDAG &DAG)
static SDValue foldBoolSelectToLogic(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
static std::optional< SDByteProvider > calculateByteProvider(SDValue Op, unsigned Index, unsigned Depth, std::optional< uint64_t > VectorIndex, unsigned StartingIndex=0)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines the DenseMap class.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static bool isSigned(unsigned int Opcode)
static bool isUndef(ArrayRef< int > Mask)
static MaybeAlign getAlign(Value *Ptr)
iv Induction Variable Users
static Value * simplifyDivRem(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1, const SimplifyQuery &Q, unsigned MaxRecurse)
Check for common or similar folds of integer division or integer remainder.
This file implements a coalescing interval map for small objects.
unsigned const TargetRegisterInfo * TRI
This file provides utility analysis objects describing memory locations.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
const SmallVectorImpl< MachineOperand > & Cond
Contains matchers for matching SelectionDAG nodes and values.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isSimple(Instruction *I)
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)
static cl::opt< bool > UseTBAA("use-tbaa-in-sched-mi", cl::Hidden, cl::init(true), cl::desc("Enable use of TBAA during MI DAG construction"))
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file implements a set that has insertion order iteration characteristics.
This file implements the SmallBitVector class.
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file describes how to lower LLVM code to machine code.
static constexpr int Concat[]
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
opStatus divide(const APFloat &RHS, roundingMode RM)
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
const fltSemantics & getSemantics() const
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
APInt umul_ov(const APInt &RHS, bool &Overflow) const
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
static void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
Dual division/remainder interface.
APInt getLoBits(unsigned numBits) const
Compute an APInt containing numBits lowbits from this APInt.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
void setBitsFrom(unsigned loBit)
Set the top bits starting from loBit.
APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
APInt trunc(unsigned width) const
Truncate to new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
APInt abs() const
Get the absolute value.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
APInt urem(const APInt &RHS) const
Unsigned remainder operation.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
bool isNegative() const
Determine sign of this APInt.
bool intersects(const APInt &RHS) const
This operation tests if there are any pairs of corresponding bits between this APInt and RHS that are...
int32_t exactLogBase2() const
APInt uadd_ov(const APInt &RHS, bool &Overflow) const
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
static APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
unsigned getSignificantBits() const
Get the minimum bit size for this signed APInt.
unsigned countLeadingZeros() const
void flipAllBits()
Toggle every bit to its opposite value.
unsigned logBase2() const
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool getBoolValue() const
Convert APInt to a boolean value.
APInt smul_ov(const APInt &RHS, bool &Overflow) const
bool isMask(unsigned numBits) const
bool ule(const APInt &RHS) const
Unsigned less or equal comparison.
APInt sext(unsigned width) const
Sign extend to a new width.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
APInt extractBits(unsigned numBits, unsigned bitPosition) const
Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
bool isOne() const
Determine if this is a value of 1.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
size - Get the array size.
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
This is an SDNode representing atomic operations.
static BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
static bool computeAliasing(const SDNode *Op0, const LocationSize NumBytes0, const SDNode *Op1, const LocationSize NumBytes1, const SelectionDAG &DAG, bool &IsAlias)
A "pseudo-class" with methods for operating on BUILD_VECTORs.
Represents known origin of an individual byte in combine pattern.
static ByteProvider getConstantZero()
static ByteProvider getSrc(std::optional< ISelOp > Val, int64_t ByteOffset, int64_t VectorOffset)
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
const APFloat & getValueAPF() const
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
bool isNegative() const
Return true if the value is negative.
bool isZero() const
Return true if the value is positive or negative zero.
ConstantFP - Floating Point Values [float, double].
bool isMinSignedValue() const
const ConstantInt * getConstantIntValue() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
This is an important base class in LLVM.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
static bool shouldExecute(unsigned CounterName)
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
static constexpr ElementCount getFixed(ScalarTy MinVal)
constexpr bool isScalar() const
Exactly one element.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
AttributeList getAttributes() const
Return the attribute list for this Function.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Helper struct to store a base, index and offset that forms an address.
This class is used to form a handle around another node that is persistent and is updated across invo...
This is an important class for using LLVM in a threaded context.
Base class for LoadSDNode and StoreSDNode.
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
static LocationSize precise(uint64_t Value)
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
TypeSize getValue() const
static auto all_valuetypes()
SimpleValueType Iteration.
static MVT getIntegerVT(unsigned BitWidth)
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
Function & getFunction()
Return the LLVM function that this machine code represents.
A description of a memory reference used in the backend.
const PseudoSourceValue * getPseudoValue() const
Flags
Flags values. These may be or'd together.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MONonTemporal
The memory access is non-temporal.
Flags getFlags() const
Return the raw flags of the source value,.
const Value * getValue() const
Return the base address of the memory access.
This class is used to represent an MGATHER node.
const SDValue & getPassThru() const
ISD::LoadExtType getExtensionType() const
const SDValue & getIndex() const
bool isIndexScaled() const
const SDValue & getScale() const
const SDValue & getBasePtr() const
const SDValue & getMask() const
ISD::MemIndexType getIndexType() const
How is Index applied to BasePtr when computing addresses.
const SDValue & getInc() const
const SDValue & getScale() const
const SDValue & getMask() const
const SDValue & getIntID() const
const SDValue & getIndex() const
const SDValue & getBasePtr() const
ISD::MemIndexType getIndexType() const
This class is used to represent an MLOAD node.
const SDValue & getBasePtr() const
bool isExpandingLoad() const
ISD::LoadExtType getExtensionType() const
const SDValue & getMask() const
const SDValue & getPassThru() const
const SDValue & getOffset() const
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc,...
This class is used to represent an MSCATTER node.
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
This class is used to represent an MSTORE node.
bool isCompressingStore() const
Returns true if the op does a compression to the vector before storing.
const SDValue & getOffset() const
const SDValue & getBasePtr() const
const SDValue & getMask() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
unsigned getAddressSpace() const
Return the address space for the associated pointer.
const MDNode * getRanges() const
Returns the Ranges that describes the dereference.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
Align getOriginalAlign() const
Returns alignment and volatility of the memory access.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getBasePtr() const
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
bool isNonTemporal() const
bool isDereferenceable() const
EVT getMemoryVT() const
Return the type of the in-memory value.
Representation for a specific memory location.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
MutableArrayRef< T > take_back(size_t N=1) const
Return a copy of *this with only the last N elements.
MutableArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
ArrayRef< SDUse > ops() const
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
void dump() const
Dump this node, for debugging.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
iterator_range< value_op_iterator > op_values() const
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
size_t use_size() const
Return the number of uses of this node.
void intersectFlagsWith(const SDNodeFlags Flags)
Clear any flags in this node that aren't also set in Flags.
TypeSize getValueSizeInBits(unsigned ResNo) const
Returns MVT::getSizeInBits(getValueType(ResNo)).
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
SDVTList getVTList() const
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
use_iterator use_begin() const
Provide iteration support to walk over all uses of an SDNode.
bool isOperandOf(const SDNode *N) const
Return true if this node is an operand of N.
const APInt & getConstantOperandAPInt(unsigned Num) const
Helper method returns the APInt of a ConstantSDNode operand.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
iterator_range< user_iterator > users()
bool hasNUsesOfValue(unsigned NUses, unsigned Value) const
Return true if there are exactly NUSES uses of the indicated value.
void setFlags(SDNodeFlags NewFlags)
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
static use_iterator use_end()
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
bool reachesChainWithoutSideEffects(SDValue Dest, unsigned Depth=2) const
Return true if this operand (which must be a chain) reaches the specified operand without crossing an...
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
bool use_empty() const
Return true if there are no nodes using value ResNo of Node.
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
unsigned getNumOperands() const
Targets can subclass this to parameterize the SelectionDAG lowering and instruction selection process...
virtual bool disableGenericCombines(CodeGenOptLevel OptLevel) const
Help to insert SDNodeFlags automatically in transforming.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
bool willNotOverflowAdd(bool IsSigned, SDValue N0, SDValue N1) const
Determine if the result of the addition of 2 nodes can never overflow.
SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT, unsigned Opcode)
Convert Op, which must be of integer type, to the integer type VT, by either any/sign/zero-extending ...
SDValue getSplatSourceVector(SDValue V, int &SplatIndex)
If V is a splatted value, return the source vector and its splat index.
unsigned ComputeMaxSignificantBits(SDValue Op, unsigned Depth=0) const
Get the upper bound on bit size for this Value Op as a signed integer.
const SDValue & getRoot() const
Return the root tag of the SelectionDAG.
SDValue getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, ISD::LoadExtType ExtTy)
bool isKnownNeverSNaN(SDValue Op, unsigned Depth=0) const
const TargetSubtargetInfo & getSubtarget() const
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, const SDLoc &dl)
Constant fold a setcc to true or false.
SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm, bool ConstantFold=true)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
SDValue getConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offs=0, bool isT=false, unsigned TargetFlags=0)
SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain)
If an existing load has uses of its chain, create a token factor node with that chain and the new mem...
bool isConstantIntBuildVectorOrConstantInt(SDValue N, bool AllowOpaques=true) const
Test whether the given value is a constant int or similar node.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
static unsigned getHasPredecessorMaxSteps()
bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
bool cannotBeOrderedNegativeFP(SDValue Op) const
Test whether the given float value is known to be positive.
SDValue getGetFPEnv(SDValue Chain, const SDLoc &dl, SDValue Ptr, EVT MemVT, MachineMemOperand *MMO)
SDValue getAssertAlign(const SDLoc &DL, SDValue V, Align A)
Return an AssertAlignSDNode.
SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal)
Returns a vector of type ResVT whose elements contain the linear sequence <0, Step,...
bool willNotOverflowSub(bool IsSigned, SDValue N0, SDValue N1) const
Determine if the result of the sub of 2 nodes can never overflow.
SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO)
Gets a node for an atomic op, produces result (if relevant) and chain and takes 2 operands.
bool shouldOptForSize() const
SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
static constexpr unsigned MaxRecursionDepth
SDValue getIndexedMaskedLoad(SDValue OrigLoad, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM)
APInt computeVectorKnownZeroElements(SDValue Op, const APInt &DemandedElts, unsigned Depth=0) const
For each demanded element of a vector, see if it is known to be zero.
std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
void salvageDebugInfo(SDNode &N)
To be invoked on an SDNode that is slated to be erased.
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getGatherVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
void DeleteNode(SDNode *N)
Remove the specified node from the system.
SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
SDValue simplifySelect(SDValue Cond, SDValue TVal, SDValue FVal)
Try to simplify a select/vselect into 1 of its operands or a constant.
SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
bool isConstantFPBuildVectorOrConstantFP(SDValue N) const
Test whether the given value is a constant FP or similar node.
const DataLayout & getDataLayout() const
SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl< SDValue > &Vals)
Creates a new TokenFactor containing Vals.
bool LegalizeOp(SDNode *N, SmallSetVector< SDNode *, 16 > &UpdatedNodes)
Transforms a SelectionDAG node and any operands to it into a node that is compatible with the target ...
bool doesNodeExist(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops)
Check if a node exists without modifying its flags.
void Combine(CombineLevel Level, AAResults *AA, CodeGenOptLevel OptLevel)
This iterates over the nodes in the SelectionDAG, folding certain types of nodes together,...
bool areNonVolatileConsecutiveLoads(LoadSDNode *LD, LoadSDNode *Base, unsigned Bytes, int Dist) const
Return true if loads are next to each other and can be merged.
SDValue getMaskedHistogram(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
bool willNotOverflowMul(bool IsSigned, SDValue N0, SDValue N1) const
Determine if the result of the mul of 2 nodes can never overflow.
SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
bool isGuaranteedNotToBeUndefOrPoison(SDValue Op, bool PoisonOnly=false, unsigned Depth=0) const
Return true if this function can prove that Op is never poison and, if PoisonOnly is false,...
SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getSplatVector(EVT VT, const SDLoc &DL, SDValue Op)
MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
void RemoveDeadNodes()
This method deletes all unreachable nodes in the SelectionDAG.
bool isConstantValueOfAnyType(SDValue N) const
SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
bool isKnownToBeAPowerOfTwo(SDValue Val, unsigned Depth=0) const
Test if the given value is known to have exactly one bit set.
bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
SDValue getIndexedStore(SDValue OrigStore, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM)
SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
SDValue getSetFPEnv(SDValue Chain, const SDLoc &dl, SDValue Ptr, EVT MemVT, MachineMemOperand *MMO)
SDValue getBoolExtOrTrunc(SDValue Op, const SDLoc &SL, EVT VT, EVT OpVT)
Convert Op, which must be of integer type, to the integer type VT, by using an extension appropriate ...
SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
const TargetMachine & getTarget() const
SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
iterator_range< allnodes_iterator > allnodes()
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond)
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
SDValue getLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Mask, SDValue EVL, MachinePointerInfo PtrInfo, EVT MemVT, Align Alignment, MachineMemOperand::Flags MMOFlags, const AAMDNodes &AAInfo, const MDNode *Ranges=nullptr, bool IsExpanding=false)
SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
SDValue getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getValueType(EVT)
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
bool isKnownNeverNaN(SDValue Op, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN.
SDValue getIndexedMaskedStore(SDValue OrigStore, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM)
const TargetLibraryInfo & getLibInfo() const
unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
bool MaskedVectorIsZero(SDValue Op, const APInt &DemandedElts, unsigned Depth=0) const
Return true if 'Op' is known to be zero in DemandedElts.
SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT)
Create a true or false constant of type VT using the target's BooleanContent for type OpVT.
SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
bool canCreateUndefOrPoison(SDValue Op, const APInt &DemandedElts, bool PoisonOnly=false, bool ConsiderFlags=true, unsigned Depth=0) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
OverflowKind computeOverflowForUnsignedAdd(SDValue N0, SDValue N1) const
Determine if the result of the unsigned addition of 2 nodes can overflow.
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
bool isSafeToSpeculativelyExecuteNode(const SDNode *N) const
Check if the provided node is save to speculatively executed given its current arguments.
KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
bool isKnownToBeAPowerOfTwoFP(SDValue Val, unsigned Depth=0) const
Test if the given fp value is known to be an integer power-of-2, either positive or negative.
std::optional< uint64_t > getValidShiftAmount(SDValue V, const APInt &DemandedElts, unsigned Depth=0) const
If a SHL/SRA/SRL node V has a uniform shift amount that is less than the element bit-width of the shi...
LLVMContext * getContext() const
SDValue simplifyFPBinop(unsigned Opcode, SDValue X, SDValue Y, SDNodeFlags Flags)
Try to simplify a floating-point binary operation into 1 of its operands or a constant.
const SDValue & setRoot(SDValue N)
Set the current root tag of the SelectionDAG.
bool isUndef(unsigned Opcode, ArrayRef< SDValue > Ops)
Return true if the result of this operation is always undefined.
SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags)
Get the specified node if it's already available, or else return NULL.
std::optional< bool > isBoolConstant(SDValue N, bool AllowTruncation=false) const
Check if a value \op N is a constant using the target's BooleanContent for its type.
SDValue getIndexedLoad(SDValue OrigLoad, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
DenormalMode getDenormalMode(EVT VT) const
Return the current function's default denormal handling kind for the given floating point type.
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
static unsigned getOpcode_EXTEND(unsigned Opcode)
Convert *_EXTEND_VECTOR_INREG to *_EXTEND opcode.
bool isADDLike(SDValue Op, bool NoWrap=false) const
Return true if the specified operand is an ISD::OR or ISD::XOR node that can be treated as an ISD::AD...
SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
SDValue simplifyShift(SDValue X, SDValue Y)
Try to simplify a shift into 1 of its operands or a constant.
void transferDbgValues(SDValue From, SDValue To, unsigned OffsetInBits=0, unsigned SizeInBits=0, bool InvalidateDbg=true)
Transfer debug values from one node to another, while optionally generating fragment expressions for ...
SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
SDValue getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, bool IsTruncating=false)
A vector that has set insertion semantics.
bool remove(const value_type &X)
Remove an item from the set vector.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
value_type pop_back_val()
static bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getMaskElt(unsigned Idx) const
int getSplatIndex() const
ArrayRef< int > getMask() const
static void commuteMask(MutableArrayRef< int > Mask)
Change values in a shuffle permute mask assuming the two vector operands have swapped position.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
bool has(LibFunc F) const
Tests whether a library function is available.
virtual bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT) const
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
bool isOperationExpand(unsigned Op, EVT VT) const
Return true if the specified operation is illegal on this target or unlikely to be made legal with cu...
virtual bool preferSextInRegOfTruncate(EVT TruncVT, EVT VT, EVT ExtVT) const
virtual bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
virtual bool hasAndNot(SDValue X) const
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
virtual bool isShuffleMaskLegal(ArrayRef< int >, EVT) const
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
virtual bool enableAggressiveFMAFusion(EVT VT) const
Return true if target always benefits from combining into FMA for a given value type.
bool isIndexedStoreLegal(unsigned IdxMode, EVT VT) const
Return true if the specified indexed load is legal on this target.
SDValue promoteTargetBoolean(SelectionDAG &DAG, SDValue Bool, EVT ValVT) const
Promote the given target boolean to a target boolean of the given type.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual bool canCombineTruncStore(EVT ValVT, EVT MemVT, bool LegalOnly) const
virtual bool convertSetCCLogicToBitwiseLogic(EVT VT) const
Use bitwise logic to make pairs of compares more efficient.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual bool isVectorLoadExtDesirable(SDValue ExtVal) const
Return true if folding a vector load into ExtVal (a sign, zero, or any extend node) is profitable.
int getRecipEstimateSqrtEnabled(EVT VT, MachineFunction &MF) const
Return a ReciprocalEstimate enum value for a square root of the given type based on the function's at...
virtual bool isSExtCheaperThanZExt(EVT FromTy, EVT ToTy) const
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
virtual MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual bool isFPExtFoldable(const MachineInstr &MI, unsigned Opcode, LLT DestTy, LLT SrcTy) const
Return true if an fpext operation input to an Opcode operation is free (for instance,...
virtual bool hasBitTest(SDValue X, SDValue Y) const
Return true if the target has a bit-test instruction: (X & (1 << Y)) ==/!= 0 This knowledge can be us...
bool isTruncStoreLegal(EVT ValVT, EVT MemVT) const
Return true if the specified store with truncation is legal on this target.
virtual bool isLoadBitCastBeneficial(EVT LoadVT, EVT BitcastVT, const SelectionDAG &DAG, const MachineMemOperand &MMO) const
Return true if the following transform is beneficial: fold (conv (load x)) -> (load (conv*)x) On arch...
virtual bool areTwoSDNodeTargetMMOFlagsMergeable(const MemSDNode &NodeX, const MemSDNode &NodeY) const
Return true if it is valid to merge the TargetMMOFlags in two SDNodes.
virtual bool isCommutativeBinOp(unsigned Opcode) const
Returns true if the opcode is a commutative binary operation.
virtual bool isFPImmLegal(const APFloat &, EVT, bool ForCodeSize=false) const
Returns true if the target can instruction select the specified FP immediate natively.
virtual bool isExtractVecEltCheap(EVT VT, unsigned Index) const
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
virtual bool optimizeFMulOrFDivAsShiftAddBitcast(SDNode *N, SDValue FPConst, SDValue IntPow2) const
virtual bool shouldNormalizeToSelectSequence(LLVMContext &Context, EVT VT) const
Returns true if we should normalize select(N0&N1, X, Y) => select(N0, select(N1, X,...
virtual bool preferScalarizeSplat(SDNode *N) const
bool isIndexedMaskedLoadLegal(unsigned IdxMode, EVT VT) const
Return true if the specified indexed load is legal on this target.
bool isOperationCustom(unsigned Op, EVT VT) const
Return true if the operation uses custom lowering, regardless of whether the type is legal or not.
virtual bool reduceSelectOfFPConstantLoads(EVT CmpOpVT) const
Return true if it is profitable to convert a select of FP constants into a constant pool load whose a...
bool hasBigEndianPartOrdering(EVT VT, const DataLayout &DL) const
When splitting a value of the specified type into parts, does the Lo or Hi part come first?...
EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL) const
Returns the type for the shift amount of a shift opcode.
virtual bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
virtual bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
virtual bool isFsqrtCheap(SDValue X, SelectionDAG &DAG) const
Return true if SQRT(X) shouldn't be replaced with X*RSQRT(X).
int getDivRefinementSteps(EVT VT, MachineFunction &MF) const
Return the refinement step count for a division of the given type based on the function's attributes.
virtual bool shouldFoldConstantShiftPairToMask(const SDNode *N, CombineLevel Level) const
Return true if it is profitable to fold a pair of shifts into a mask.
virtual bool isTruncateFree(Type *FromTy, Type *ToTy) const
Return true if it's free to truncate a value of type FromTy to type ToTy.
virtual bool shouldAvoidTransformToShift(EVT VT, unsigned Amount) const
Return true if creating a shift of the type by the given amount is not profitable.
virtual EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const
Return the ValueType of the result of SETCC operations.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
virtual bool shouldFoldSelectWithSingleBitTest(EVT VT, const APInt &AndMask) const
BooleanContent getBooleanContents(bool isVec, bool isFloat) const
For targets without i1 registers, this gives the nature of the high-bits of boolean values held in ty...
virtual bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT) const
Return true if pulling a binary operation into a select with an identity constant is profitable.
virtual bool shouldReassociateReduction(unsigned RedOpc, EVT VT) const
bool isCondCodeLegal(ISD::CondCode CC, MVT VT) const
Return true if the specified condition code is legal for a comparison of the specified types on this ...
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
int getRecipEstimateDivEnabled(EVT VT, MachineFunction &MF) const
Return a ReciprocalEstimate enum value for a division of the given type based on the function's attri...
virtual bool preferIncOfAddToSubOfNot(EVT VT) const
These two forms are equivalent: sub y, (xor x, -1) add (add x, 1), y The variant with two add's is IR...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
virtual bool isLegalAddImmediate(int64_t) const
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
virtual bool shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT) const
Return true if it is profitable to reduce a load to a smaller type.
virtual bool isProfitableToCombineMinNumMaxNum(EVT VT) const
virtual bool isFNegFree(EVT VT) const
Return true if an fneg operation is free to the point where it is never worthwhile to replace it with...
@ ZeroOrOneBooleanContent
@ UndefinedBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual bool isIntDivCheap(EVT VT, AttributeList Attr) const
Return true if integer divide is usually cheaper than a sequence of several shifts,...
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool mergeStoresAfterLegalization(EVT MemVT) const
Allow store merging for the specified type after legalization in addition to before legalization.
virtual bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
Return true if the target supports a memory access of this type for the given address space and align...
unsigned getGatherAllAliasesMaxDepth() const
virtual bool storeOfVectorConstantIsCheap(bool IsZero, EVT MemVT, unsigned NumElem, unsigned AddrSpace) const
Return true if it is expected to be cheaper to do a store of vector constant with the given size and ...
virtual bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
virtual bool isMultiStoresCheaperThanBitsMerge(EVT LTy, EVT HTy) const
Return true if it is cheaper to split the store of a merged int val from a pair of smaller values int...
bool isLoadExtLegalOrCustom(unsigned ExtType, EVT ValVT, EVT MemVT) const
Return true if the specified load with extension is legal or custom on this target.
bool isAtomicLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const
Return true if the specified atomic load with extension is legal on this target.
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
virtual bool shouldFoldMaskToVariableShiftPair(SDValue X) const
There are two ways to clear extreme bits (either low or high): Mask: x & (-1 << y) (the instcombine c...
bool isIndexedLoadLegal(unsigned IdxMode, EVT VT) const
Return true if the specified indexed load is legal on this target.
virtual bool canMergeStoresTo(unsigned AS, EVT MemVT, const MachineFunction &MF) const
Returns if it's reasonable to merge stores to MemVT size.
virtual bool preferABDSToABSWithNSW(EVT VT) const
bool isLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const
Return true if the specified load with extension is legal on this target.
AndOrSETCCFoldKind
Enum of different potentially desirable ways to fold (and/or (setcc ...), (setcc ....
virtual bool shouldScalarizeBinop(SDValue VecOp) const
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
virtual bool isStoreBitCastBeneficial(EVT StoreVT, EVT BitcastVT, const SelectionDAG &DAG, const MachineMemOperand &MMO) const
Return true if the following transform is beneficial: (store (y (conv x)), y*)) -> (store x,...
bool isIndexedMaskedStoreLegal(unsigned IdxMode, EVT VT) const
Return true if the specified indexed load is legal on this target.
virtual bool isVectorClearMaskLegal(ArrayRef< int >, EVT) const
Similar to isShuffleMaskLegal.
bool hasTargetDAGCombine(ISD::NodeType NT) const
If true, the target has custom DAG combine transformations that it can perform for the specified node...
virtual bool shouldSplatInsEltVarIndex(EVT) const
Return true if inserting a scalar into a variable element of an undef vector is more efficiently hand...
NegatibleCost
Enum that specifies when a float negation is beneficial.
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
int getSqrtRefinementSteps(EVT VT, MachineFunction &MF) const
Return the refinement step count for a square root of the given type based on the function's attribut...
virtual unsigned preferedOpcodeForCmpEqPiecesOfOperand(EVT VT, unsigned ShiftOpc, bool MayTransformRotate, const APInt &ShiftOrRotateAmt, const std::optional< APInt > &AndMask) const
virtual bool isFMADLegal(const MachineInstr &MI, LLT Ty) const
Returns true if MI can be combined with another instruction to form TargetOpcode::G_FMAD.
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
virtual bool aggressivelyPreferBuildVectorSources(EVT VecVT) const
virtual bool shouldRemoveExtendFromGSIndex(SDValue Extend, EVT DataVT) const
virtual bool isFAbsFree(EVT VT) const
Return true if an fabs operation is free to the point where it is never worthwhile to replace it with...
LegalizeAction getOperationAction(unsigned Op, EVT VT) const
Return how this operation should be treated: either it is legal, needs to be promoted to a larger siz...
virtual bool generateFMAsInMachineCombiner(EVT VT, CodeGenOptLevel OptLevel) const
virtual bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AddrSpace, Instruction *I=nullptr) const
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
virtual bool hasPairedLoad(EVT, Align &) const
Return true if the target supplies and combines to a paired load two loaded values of type LoadedType...
virtual bool convertSelectOfConstantsToMath(EVT VT) const
Return true if a select of constants (select Cond, C1, C2) should be transformed into simple math ops...
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
virtual SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const
Hooks for building estimates in place of slower divisions and square roots.
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
virtual bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, SDValue N1) const
SDValue getCheaperOrNeutralNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, const NegatibleCost CostThreshold=NegatibleCost::Neutral, unsigned Depth=0) const
SDValue getCheaperNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, unsigned Depth=0) const
This is the helper function to return the newly negated expression only when the cost is cheaper.
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "look through" ops that don't contri...
SDValue expandABS(SDNode *N, SelectionDAG &DAG, bool IsNegative=false) const
Expand ABS nodes.
virtual bool IsDesirableToPromoteOp(SDValue, EVT &) const
This method query the target whether it is beneficial for dag combiner to promote the specified node.
SDValue BuildSDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, bool IsAfterLegalTypes, SmallVectorImpl< SDNode * > &Created) const
Given an ISD::SDIV node expressing a divide by constant, return a DAG expression to select that will ...
virtual bool isTypeDesirableForOp(unsigned, EVT VT) const
Return true if the target has native support for the specified value type and it is 'desirable' to us...
SDValue BuildUDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, bool IsAfterLegalTypes, SmallVectorImpl< SDNode * > &Created) const
Given an ISD::UDIV node expressing a divide by constant, return a DAG expression to select that will ...
virtual SDValue getNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, NegatibleCost &Cost, unsigned Depth=0) const
Return the newly negated expression if the cost is not expensive and set the cost in Cost to indicate...
virtual SDValue getSqrtInputTest(SDValue Operand, SelectionDAG &DAG, const DenormalMode &Mode) const
Return a target-dependent comparison result if the input operand is suitable for use with a square ro...
SDValue buildLegalVectorShuffle(EVT VT, const SDLoc &DL, SDValue N0, SDValue N1, MutableArrayRef< int > Mask, SelectionDAG &DAG) const
Tries to build a legal vector shuffle using the provided parameters or equivalent variations.
virtual SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps) const
Return a reciprocal estimate value for the input operand.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
bool isConstFalseVal(SDValue N) const
Return if the N is a constant or constant vector equal to the false value from getBooleanContents().
virtual SDValue getSqrtResultForDenormInput(SDValue Operand, SelectionDAG &DAG) const
Return a target-dependent result if the input operand is not suitable for use with a square root esti...
virtual bool getPostIndexedAddressParts(SDNode *, SDNode *, SDValue &, SDValue &, ISD::MemIndexedMode &, SelectionDAG &) const
Returns true by value, base pointer and offset pointer and addressing mode by reference if this node ...
SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, bool foldBooleans, DAGCombinerInfo &DCI, const SDLoc &dl) const
Try to simplify a setcc built with the specified operands and cc.
virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const
Return true if folding a constant offset with the given GlobalAddress is legal.
bool isConstTrueVal(SDValue N) const
Return if the N is a constant or constant vector equal to the true value from getBooleanContents().
SDValue getVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT, SDValue Index) const
Get a pointer to vector element Idx located in memory for a vector of type VecVT starting at a base a...
virtual bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const
Return true if it is profitable to move this shift by a constant amount through its operand,...
virtual unsigned combineRepeatedFPDivisors() const
Indicate whether this target prefers to combine FDIVs with the same divisor.
virtual AndOrSETCCFoldKind isDesirableToCombineLogicOpOfSETCC(const SDNode *LogicOp, const SDNode *SETCC0, const SDNode *SETCC1) const
virtual bool getPreIndexedAddressParts(SDNode *, SDValue &, SDValue &, ISD::MemIndexedMode &, SelectionDAG &) const
Returns true by value, base pointer and offset pointer and addressing mode by reference if the node's...
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
This method will be invoked for all target nodes and for any target-independent nodes that the target...
virtual SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, SmallVectorImpl< SDNode * > &Created) const
Targets may override this function to provide custom SDIV lowering for power-of-2 denominators.
virtual SDValue BuildSREMPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, SmallVectorImpl< SDNode * > &Created) const
Targets may override this function to provide custom SREM lowering for power-of-2 denominators.
virtual bool isDesirableToTransformToIntegerOp(unsigned, EVT) const
Return true if it is profitable for dag combiner to transform a floating point op of specified opcode...
unsigned UnsafeFPMath
UnsafeFPMath - This flag is enabled when the -enable-unsafe-fp-math flag is specified on the command ...
unsigned NoSignedZerosFPMath
NoSignedZerosFPMath - This flag is enabled when the -enable-no-signed-zeros-fp-math is specified on t...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual bool useAA() const
Enable use of alias analysis during code generation (during MI scheduling, DAGCombine,...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
const fltSemantics & getFltSemantics() const
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
unsigned getOperandNo() const
Return the operand # of this use in its User.
Value * getOperand(unsigned i) const
This class is used to represent an VP_GATHER node.
const SDValue & getScale() const
ISD::MemIndexType getIndexType() const
How is Index applied to BasePtr when computing addresses.
const SDValue & getVectorLength() const
const SDValue & getIndex() const
const SDValue & getBasePtr() const
bool isIndexScaled() const
const SDValue & getMask() const
This class is used to represent an VP_SCATTER node.
const SDValue & getValue() const
This class is used to represent EVT's, which are used to parameterize some operations.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
user_iterator user_begin()
bool hasOneUse() const
Return true if there is exactly one use of this value.
iterator_range< user_iterator > users()
iterator_range< use_iterator > uses()
int getNumOccurrences() const
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getFixedValue() const
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char IsVolatile[]
Key for Kernel::Arg::Metadata::mIsVolatile.
const APInt & smin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be signed.
const APInt & smax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be signed.
const APInt & umin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be unsigned.
const APInt & umax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be unsigned.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
CondCode getSetCCAndOperation(CondCode Op1, CondCode Op2, EVT Type)
Return the result of a logical AND between different comparisons of identical values: ((X op1 Y) & (X...
bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ SMULFIX
RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on 2 integers with the same...
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADDC
Carry-setting nodes for multiple precision addition and subtraction.
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SMULFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ SETCCCARRY
Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but op #2 is a boolean indicating ...
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ AssertAlign
AssertAlign - These nodes record if a register contains a value that has a known alignment and the tr...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EntryToken
EntryToken - This is the marker used to indicate the start of a region.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ VSCALE
VSCALE(IMM) - Returns the runtime scaling factor used to calculate the number of elements within a sc...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two values.
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
@ SMULO
Same for multiplication.
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ LIFETIME_START
This corresponds to the llvm.lifetime.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ MGATHER
Masked gather and scatter - load and store operations for a vector of random addresses with additiona...
@ HANDLENODE
HANDLENODE node - Used as a handle for various purposes.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ TargetConstant
TargetConstant* - Like Constant*, but the DAG does not do any folding, simplification,...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ GET_FPENV_MEM
Gets the current floating-point environment.
@ CARRY_FALSE
CARRY_FALSE - This node is used when folding other nodes, like ADDC/SUBC, which indicate the carry re...
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ ADDE
Carry-using nodes for multiple precision addition and subtraction.
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ EXPERIMENTAL_VECTOR_HISTOGRAM
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ BRCOND
BRCOND - Conditional branch.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ CALLSEQ_START
CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end of a call sequence,...
@ SET_FPENV_MEM
Sets the current floating point environment.
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ TRUNCATE_SSAT_S
TRUNCATE_[SU]SAT_[SU] - Truncate for saturated operand [SU] located in middle, prefix for SAT means i...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ SADDO_CARRY
Carry-using overflow-aware nodes for multiple precision addition and subtraction.
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isIndexTypeSigned(MemIndexType IndexType)
bool isExtVecInRegOpcode(unsigned Opcode)
bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool matchUnaryPredicate(SDValue Op, std::function< bool(ConstantSDNode *)> Match, bool AllowUndefs=false)
Hook for matching ConstantSDNode predicate.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
bool matchUnaryFpPredicate(SDValue Op, std::function< bool(ConstantFPSDNode *)> Match, bool AllowUndefs=false)
Hook for matching ConstantFPSDNode predicate.
bool isFPEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with floati...
bool isExtOpcode(unsigned Opcode)
bool isConstantSplatVectorAllZeros(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are 0 o...
bool isVPBinaryOp(unsigned Opcode)
Whether this is a vector-predicated binary operation opcode.
CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isBitwiseLogicOp(unsigned Opcode)
Whether this is bitwise logic opcode.
std::optional< unsigned > getVPMaskIdx(unsigned Opcode)
The operand position of the vector mask.
bool isUNINDEXEDLoad(const SDNode *N)
Returns true if the specified node is an unindexed load.
std::optional< unsigned > getVPExplicitVectorLengthIdx(unsigned Opcode)
The operand position of the explicit vector length parameter.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
bool allOperandsUndef(const SDNode *N)
Return true if the node has at least one operand and all operands of the specified node are ISD::UNDE...
CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
MemIndexType
MemIndexType enum - This enum defines how to interpret MGATHER/SCATTER's index parameter when calcula...
bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
NodeType getInverseMinMaxOpcode(unsigned MinMaxOpc)
Given a MinMaxOpc of ISD::(U|S)MIN or ISD::(U|S)MAX, returns ISD::(U|S)MAX and ISD::(U|S)MIN,...
bool matchBinaryPredicate(SDValue LHS, SDValue RHS, std::function< bool(ConstantSDNode *, ConstantSDNode *)> Match, bool AllowUndefs=false, bool AllowTypeMismatch=false)
Attempt to match a binary predicate against a pair of scalar/splat constants or every element of a pa...
bool isVPReduction(unsigned Opcode)
Whether this is a vector-predicated reduction opcode.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isBuildVectorOfConstantFPSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantFPSDNode or undef.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
CondCode getSetCCOrOperation(CondCode Op1, CondCode Op2, EVT Type)
Return the result of a logical OR between different comparisons of identical values: ((X op1 Y) | (X ...
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
class_match< BinaryOperator > m_BinOp()
Match an arbitrary binary operation and ignore it.
m_Intrinsic_Ty< Opnd0 >::Ty m_BitReverse(const Opnd0 &Op0)
BinaryOp_match< LHS, RHS, Instruction::Xor > m_Xor(const LHS &L, const RHS &R)
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
MaxMin_match< ICmpInst, LHS, RHS, smin_pred_ty > m_SMin(const LHS &L, const RHS &R)
CastInst_match< OpTy, FPToUIInst > m_FPToUI(const OpTy &Op)
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
deferredval_ty< Value > m_Deferred(Value *const &V)
Like m_Specific(), but works if the specific value to match is determined as part of the same match()...
BinaryOp_match< cst_pred_ty< is_zero_int >, ValTy, Instruction::Sub > m_Neg(const ValTy &V)
Matches a 'Neg' as 'sub 0, V'.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
MaxMin_match< ICmpInst, LHS, RHS, umax_pred_ty > m_UMax(const LHS &L, const RHS &R)
CastOperator_match< OpTy, Instruction::BitCast > m_BitCast(const OpTy &Op)
Matches BitCast.
MaxMin_match< ICmpInst, LHS, RHS, smax_pred_ty > m_SMax(const LHS &L, const RHS &R)
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)
Matches a BinaryOperator with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
BinaryOp_match< cst_pred_ty< is_all_ones >, ValTy, Instruction::Xor, true > m_Not(const ValTy &V)
Matches a 'Not' as 'xor V, -1' or 'xor -1, V'.
BinaryOp_match< LHS, RHS, Instruction::Or > m_Or(const LHS &L, const RHS &R)
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
MaxMin_match< ICmpInst, LHS, RHS, umin_pred_ty > m_UMin(const LHS &L, const RHS &R)
Libcall
RTLIB::Libcall enum - This enum defines all of the runtime library calls the backend can emit.
@ Undef
Value of the register doesn't matter.
Opcode_match m_Opc(unsigned Opcode)
BinaryOpc_match< LHS, RHS > m_Srl(const LHS &L, const RHS &R)
auto m_SpecificVT(EVT RefVT, const Pattern &P)
Match a specific ValueType.
BinaryOpc_match< LHS, RHS > m_Sra(const LHS &L, const RHS &R)
auto m_UMinLike(const LHS &L, const RHS &R)
auto m_UMaxLike(const LHS &L, const RHS &R)
Or< Preds... > m_AnyOf(const Preds &...preds)
And< Preds... > m_AllOf(const Preds &...preds)
TernaryOpc_match< T0_P, T1_P, T2_P > m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC)
UnaryOpc_match< Opnd > m_AnyExt(const Opnd &Op)
auto m_SMaxLike(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_Ctlz(const Opnd &Op)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
UnaryOpc_match< Opnd > m_UnaryOp(unsigned Opc, const Opnd &Op)
auto m_SMinLike(const LHS &L, const RHS &R)
CondCode_match m_SpecificCondCode(ISD::CondCode CC)
Match a conditional code SDNode with a specific ISD::CondCode.
NUses_match< 1, Value_match > m_OneUse()
CondCode_match m_CondCode()
Match any conditional code SDNode.
TernaryOpc_match< T0_P, T1_P, T2_P, true, false > m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC)
bool sd_context_match(SDValue N, const MatchContext &Ctx, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any interger constants or splat of an integer constant.
initializer< Ty > init(const Ty &Val)
int ilogb(const IEEEFloat &Arg)
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
bool operator<(int64_t V1, const APSInt &V2)
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
int popcount(T Value) noexcept
Count the number of set bits in a value.
bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
bool isAllOnesOrAllOnesSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant -1 integer or a splatted vector of a constant -1 integer (with...
SDValue getBitwiseNotOperand(SDValue V, SDValue Mask, bool AllowUndefs)
If V is a bitwise not, returns the inverted operand.
SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
llvm::SmallVector< int, 16 > createUnaryMask(ArrayRef< int > Mask, unsigned NumElts)
Given a shuffle mask for a binary shuffle, create the equivalent shuffle mask assuming both operands ...
bool isIntOrFPConstant(SDValue V)
Return true if V is either a integer or FP constant.
bool operator!=(uint64_t V1, const APInt &V2)
bool operator>=(int64_t V1, const APSInt &V2)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt & operator+=(DynamicAPInt &A, int64_t B)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
bool isMinSignedConstant(SDValue V)
Returns true if V is a constant min signed integer value.
ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned M1(unsigned Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
bool isConstantOrConstantVector(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowFP=true, bool AllowOpaqueConstants=true)
Return true if the specified instruction is known to be a constant, or a vector of constants.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
bool operator>(int64_t V1, const APSInt &V2)
bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
auto reverse(ContainerTy &&C)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
detail::ValueMatchesPoly< M > HasValue(M Matcher)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
SDValue peekThroughTruncates(SDValue V)
Return the non-truncated source operand of V if it exists.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
SDValue peekThroughOneUseBitcasts(SDValue V)
Return the non-bitcasted and one-use source operand of V if it exists.
CodeGenOptLevel
Code generation optimization level.
bool isOneOrOneSplat(SDValue V, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 integer (with n...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
void narrowShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Replace each shuffle mask index with the scaled sequential indices for an equivalent mask of narrowed...
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr unsigned BitWidth
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
void getShuffleMaskWithWidestElts(ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Repetitively apply widenShuffleMaskElts() for as long as it succeeds, to get the shuffle mask with wi...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
bool isNullFPConstant(SDValue V)
Returns true if V is an FP constant with a value of positive zero.
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
unsigned Log2(Align A)
Returns the log2 of the alignment.
bool isNeutralConstant(unsigned Opc, SDNodeFlags Flags, SDValue V, unsigned OperandNo)
Returns true if V is a neutral element of Opc with Flags.
bool operator<=(int64_t V1, const APSInt &V2)
bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
int getSplatIndex(ArrayRef< int > Mask)
If all non-negative Mask elements are the same value, return that value.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
AAMDNodes concat(const AAMDNodes &Other) const
Determine the best AAMDNodes after concatenating two different locations together.
static ExponentType semanticsMinExponent(const fltSemantics &)
static constexpr roundingMode rmNearestTiesToEven
static ExponentType semanticsMaxExponent(const fltSemantics &)
static unsigned int semanticsPrecision(const fltSemantics &)
opStatus
IEEE-754R 7: Default exception handling.
static unsigned int semanticsIntSizeInBits(const fltSemantics &, bool)
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
Represent subnormal handling kind for floating point instruction inputs and outputs.
static constexpr DenormalMode getIEEE()
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool knownBitsLE(EVT VT) const
Return true if we know at compile time this has fewer than or the same bits as VT.
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isScalableVT() const
Return true if the type is a scalable type.
bool isFixedLengthVector() const
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
bool bitsEq(EVT VT) const
Return true if this has the same number of bits as VT.
Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isRound() const
Return true if the size is a power-of-two number of bytes.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
bool knownBitsGE(EVT VT) const
Return true if we know at compile time this has more than or the same bits as VT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isExtended() const
Test if the given EVT is extended (as opposed to being simple).
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool isZeroSized() const
Test if the given EVT has zero size, this will fail if called on a scalable type.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool isNonNegative() const
Returns true if this value is known to be non-negative.
unsigned countMinTrailingZeros() const
Returns the minimum number of trailing zero bits.
bool isConstant() const
Returns true if we know the value of all bits.
unsigned countMaxActiveBits() const
Returns the maximum number of bits needed to represent all possible unsigned values with these known ...
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
bool isAllOnes() const
Returns true if value is all one bits.
const APInt & getConstant() const
Returns the value when all bits have a known value.
This class contains a discriminated union of information about pointers in memory operands,...
unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
static MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoUnsignedWrap() const
bool hasNoSignedWrap() const
bool hasAllowReassociation() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
Clients of various APIs that cause global effects on the DAG can optionally implement this interface.
virtual void NodeDeleted(SDNode *N, SDNode *E)
The node N that was deleted and, if E is not null, an equivalent node E that replaced it.
virtual void NodeInserted(SDNode *N)
The node N that was inserted.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
void AddToWorklist(SDNode *N)
bool recursivelyDeleteUnusedNodes(SDNode *N)
SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
void CommitTargetLoweringOpt(const TargetLoweringOpt &TLO)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...