22#include "llvm/IR/IntrinsicsHexagon.h"
27#define DEBUG_TYPE "hexagon-isel"
28#define PASS_NAME "Hexagon DAG->DAG Pattern Instruction Selection"
33 cl::desc(
"Rebalance address calculation trees to improve "
34 "instruction selection"));
41 cl::desc(
"Rebalance address tree only if this allows optimizations"));
46 cl::init(
false),
cl::desc(
"Rebalance address tree only if it is imbalanced"));
55#define GET_DAGISEL_BODY HexagonDAGToDAGISel
56#include "HexagonGenDAGISel.inc"
75 int32_t Inc = cast<ConstantSDNode>(
Offset.getNode())->getSExtValue();
76 EVT LoadedVT = LD->getMemoryVT();
83 bool IsValidInc = HII->isValidAutoIncImm(LoadedVT, Inc);
89 Opcode = IsValidInc ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrub_io;
91 Opcode = IsValidInc ? Hexagon::L2_loadrb_pi : Hexagon::L2_loadrb_io;
95 Opcode = IsValidInc ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadruh_io;
97 Opcode = IsValidInc ? Hexagon::L2_loadrh_pi : Hexagon::L2_loadrh_io;
103 Opcode = IsValidInc ? Hexagon::L2_loadri_pi : Hexagon::L2_loadri_io;
110 Opcode = IsValidInc ? Hexagon::L2_loadrd_pi : Hexagon::L2_loadrd_io;
120 if (isAlignedMemNode(LD)) {
121 if (LD->isNonTemporal())
122 Opcode = IsValidInc ? Hexagon::V6_vL32b_nt_pi : Hexagon::V6_vL32b_nt_ai;
124 Opcode = IsValidInc ? Hexagon::V6_vL32b_pi : Hexagon::V6_vL32b_ai;
126 Opcode = IsValidInc ? Hexagon::V6_vL32Ub_pi : Hexagon::V6_vL32Ub_ai;
133 SDValue IncV = CurDAG->getTargetConstant(Inc, dl, MVT::i32);
139 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
140 return CurDAG->getMachineNode(Hexagon::A4_combineir, dl, MVT::i64,
144 return CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
153 EVT ValueVT = LD->getValueType(0);
162 MachineSDNode *L = CurDAG->getMachineNode(Opcode, dl, ValueVT,
163 MVT::i32, MVT::Other,
Base,
165 CurDAG->setNodeMemRefs(L, {
MemOp});
169 if (LD->getValueType(0) == MVT::i64)
173 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
174 MachineSDNode *L = CurDAG->getMachineNode(Opcode, dl, ValueVT, MVT::Other,
176 CurDAG->setNodeMemRefs(L, {
MemOp});
178 MachineSDNode *
A = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
182 if (LD->getValueType(0) == MVT::i64)
186 ReplaceUses(
From, To, 3);
187 CurDAG->RemoveDeadNode(LD);
197 static std::map<unsigned,unsigned> LoadPciMap = {
198 { Intrinsic::hexagon_circ_ldb, Hexagon::L2_loadrb_pci },
199 { Intrinsic::hexagon_circ_ldub, Hexagon::L2_loadrub_pci },
200 { Intrinsic::hexagon_circ_ldh, Hexagon::L2_loadrh_pci },
201 { Intrinsic::hexagon_circ_lduh, Hexagon::L2_loadruh_pci },
202 { Intrinsic::hexagon_circ_ldw, Hexagon::L2_loadri_pci },
203 { Intrinsic::hexagon_circ_ldd, Hexagon::L2_loadrd_pci },
205 auto FLC = LoadPciMap.find(IntNo);
206 if (FLC != LoadPciMap.end()) {
207 EVT ValTy = (IntNo == Intrinsic::hexagon_circ_ldd) ? MVT::i64 : MVT::i32;
208 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
210 auto Inc = cast<ConstantSDNode>(IntN->
getOperand(5));
213 { IntN->getOperand(2), I, IntN->getOperand(4),
214 IntN->getOperand(0) });
229 unsigned Size = 1U << (SizeBits-1);
287 switch (
C->getConstantOperandVal(1)) {
288 case Intrinsic::hexagon_circ_ldub:
289 case Intrinsic::hexagon_circ_lduh:
292 case Intrinsic::hexagon_circ_ldw:
293 case Intrinsic::hexagon_circ_ldd:
300 if (
N->getExtensionType() != IntExt)
305 if (
C->getNumOperands() < 4 || Loc.
getNode() !=
C->getOperand(3).getNode())
327 const SDLoc &dl(IntN);
330 static const std::map<unsigned, unsigned> LoadBrevMap = {
331 { Intrinsic::hexagon_L2_loadrb_pbr, Hexagon::L2_loadrb_pbr },
332 { Intrinsic::hexagon_L2_loadrub_pbr, Hexagon::L2_loadrub_pbr },
333 { Intrinsic::hexagon_L2_loadrh_pbr, Hexagon::L2_loadrh_pbr },
334 { Intrinsic::hexagon_L2_loadruh_pbr, Hexagon::L2_loadruh_pbr },
335 { Intrinsic::hexagon_L2_loadri_pbr, Hexagon::L2_loadri_pbr },
336 { Intrinsic::hexagon_L2_loadrd_pbr, Hexagon::L2_loadrd_pbr }
338 auto FLI = LoadBrevMap.find(IntNo);
339 if (FLI != LoadBrevMap.end()) {
341 (IntNo == Intrinsic::hexagon_L2_loadrd_pbr) ? MVT::i64 : MVT::i32;
342 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
347 FLI->second, dl, RTys,
372 static std::map<unsigned,unsigned> LoadNPcMap = {
373 { Intrinsic::hexagon_L2_loadrub_pci, Hexagon::PS_loadrub_pci },
374 { Intrinsic::hexagon_L2_loadrb_pci, Hexagon::PS_loadrb_pci },
375 { Intrinsic::hexagon_L2_loadruh_pci, Hexagon::PS_loadruh_pci },
376 { Intrinsic::hexagon_L2_loadrh_pci, Hexagon::PS_loadrh_pci },
377 { Intrinsic::hexagon_L2_loadri_pci, Hexagon::PS_loadri_pci },
378 { Intrinsic::hexagon_L2_loadrd_pci, Hexagon::PS_loadrd_pci },
379 { Intrinsic::hexagon_L2_loadrub_pcr, Hexagon::PS_loadrub_pcr },
380 { Intrinsic::hexagon_L2_loadrb_pcr, Hexagon::PS_loadrb_pcr },
381 { Intrinsic::hexagon_L2_loadruh_pcr, Hexagon::PS_loadruh_pcr },
382 { Intrinsic::hexagon_L2_loadrh_pcr, Hexagon::PS_loadrh_pcr },
383 { Intrinsic::hexagon_L2_loadri_pcr, Hexagon::PS_loadri_pcr },
384 { Intrinsic::hexagon_L2_loadrd_pcr, Hexagon::PS_loadrd_pcr }
386 auto FLI = LoadNPcMap.find (IntNo);
387 if (FLI != LoadNPcMap.end()) {
388 EVT ValTy = MVT::i32;
389 if (IntNo == Intrinsic::hexagon_L2_loadrd_pci ||
390 IntNo == Intrinsic::hexagon_L2_loadrd_pcr)
392 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
395 auto Inc = cast<ConstantSDNode>(IntN->
getOperand(3));
413 static std::map<unsigned,unsigned> StoreNPcMap = {
414 { Intrinsic::hexagon_S2_storerb_pci, Hexagon::PS_storerb_pci },
415 { Intrinsic::hexagon_S2_storerh_pci, Hexagon::PS_storerh_pci },
416 { Intrinsic::hexagon_S2_storerf_pci, Hexagon::PS_storerf_pci },
417 { Intrinsic::hexagon_S2_storeri_pci, Hexagon::PS_storeri_pci },
418 { Intrinsic::hexagon_S2_storerd_pci, Hexagon::PS_storerd_pci },
419 { Intrinsic::hexagon_S2_storerb_pcr, Hexagon::PS_storerb_pcr },
420 { Intrinsic::hexagon_S2_storerh_pcr, Hexagon::PS_storerh_pcr },
421 { Intrinsic::hexagon_S2_storerf_pcr, Hexagon::PS_storerf_pcr },
422 { Intrinsic::hexagon_S2_storeri_pcr, Hexagon::PS_storeri_pcr },
423 { Intrinsic::hexagon_S2_storerd_pcr, Hexagon::PS_storerd_pcr }
425 auto FSI = StoreNPcMap.find (IntNo);
426 if (FSI != StoreNPcMap.end()) {
427 EVT RTys[] = { MVT::i32, MVT::Other };
430 auto Inc = cast<ConstantSDNode>(IntN->
getOperand(3));
469 SDValue Chain = ST->getChain();
474 int32_t Inc = cast<ConstantSDNode>(
Offset.getNode())->getSExtValue();
475 EVT StoredVT = ST->getMemoryVT();
484 Opcode = IsValidInc ? Hexagon::S2_storerb_pi : Hexagon::S2_storerb_io;
487 Opcode = IsValidInc ? Hexagon::S2_storerh_pi : Hexagon::S2_storerh_io;
493 Opcode = IsValidInc ? Hexagon::S2_storeri_pi : Hexagon::S2_storeri_io;
500 Opcode = IsValidInc ? Hexagon::S2_storerd_pi : Hexagon::S2_storerd_io;
510 if (isAlignedMemNode(ST)) {
511 if (ST->isNonTemporal())
512 Opcode = IsValidInc ? Hexagon::V6_vS32b_nt_pi : Hexagon::V6_vS32b_nt_ai;
514 Opcode = IsValidInc ? Hexagon::V6_vS32b_pi : Hexagon::V6_vS32b_ai;
516 Opcode = IsValidInc ? Hexagon::V6_vS32Ub_pi : Hexagon::V6_vS32Ub_ai;
523 if (ST->isTruncatingStore() && ValueVT.
getSizeInBits() == 64) {
526 dl, MVT::i32,
Value);
578 auto Default = [
this,
N] () ->
void { SelectCode(
N); };
584 int32_t ShlConst = cast<ConstantSDNode>(Shl_1)->getSExtValue();
591 int32_t ValConst =
C->getSExtValue() << ShlConst;
592 if (isInt<9>(ValConst)) {
595 MVT::i32, Mul_0, Val);
612 int32_t ValConst = 1 << (ShlConst + C2->getSExtValue());
613 if (isInt<9>(-ValConst)) {
616 MVT::i32, Shl2_0, Val);
644 unsigned IntNo =
N->getConstantOperandVal(1);
645 if (IntNo == Intrinsic::hexagon_V6_vgathermw ||
646 IntNo == Intrinsic::hexagon_V6_vgathermw_128B ||
647 IntNo == Intrinsic::hexagon_V6_vgathermh ||
648 IntNo == Intrinsic::hexagon_V6_vgathermh_128B ||
649 IntNo == Intrinsic::hexagon_V6_vgathermhw ||
650 IntNo == Intrinsic::hexagon_V6_vgathermhw_128B) {
654 if (IntNo == Intrinsic::hexagon_V6_vgathermwq ||
655 IntNo == Intrinsic::hexagon_V6_vgathermwq_128B ||
656 IntNo == Intrinsic::hexagon_V6_vgathermhq ||
657 IntNo == Intrinsic::hexagon_V6_vgathermhq_128B ||
658 IntNo == Intrinsic::hexagon_V6_vgathermhwq ||
659 IntNo == Intrinsic::hexagon_V6_vgathermhwq_128B) {
668 unsigned IID =
N->getConstantOperandVal(0);
671 case Intrinsic::hexagon_S2_vsplatrb:
674 case Intrinsic::hexagon_S2_vsplatrh:
677 case Intrinsic::hexagon_V6_vaddcarry:
678 case Intrinsic::hexagon_V6_vaddcarry_128B:
679 case Intrinsic::hexagon_V6_vsubcarry:
680 case Intrinsic::hexagon_V6_vsubcarry_128B:
691 if (keepsLowBits(V, Bits, U)) {
693 N->getOperand(0), U);
695 SelectCode(R.getNode());
703 MVT ResTy =
N->getValueType(0).getSimpleVT();
704 unsigned Idx =
N->getConstantOperandVal(1);
713 unsigned SubReg =
Idx == 0 ? Hexagon::isub_lo : Hexagon::isub_hi;
724 auto *CN = cast<ConstantFPSDNode>(
N);
725 APInt A = CN->getValueAPF().bitcastToAPInt();
726 if (
N->getValueType(0) == MVT::f32) {
731 if (
N->getValueType(0) == MVT::f64) {
744 if (
N->getValueType(0) == MVT::i1) {
745 assert(!(
N->getAsZExtVal() >> 1));
746 unsigned Opc = (cast<ConstantSDNode>(
N)->getSExtValue() != 0)
759 int FX = cast<FrameIndexSDNode>(
N)->getIndex();
776 Register AR = HMFI.getStackAlignBaseReg();
787 : Hexagon::A4_subp_c;
789 { N->getOperand(0), N->getOperand(1),
795 MVT ResTy =
N->getValueType(0).getSimpleVT();
797 return SelectHvxVAlign(
N);
818 M0,
N->getOperand(2),
M1);
821 N->getOperand(2),
M1);
835 N->getOperand(0),
N->getOperand(1),
844 int Mask = -cast<ConstantSDNode>(
A.getNode())->getSExtValue();
849 N->getOperand(0), M);
858 MVT OpTy =
Op.getValueType().getSimpleVT();
865 MVT ResTy =
N->getValueType(0).getSimpleVT();
873 MVT ResTy =
N->getValueType(0).getSimpleVT();
876 N->getOperand(0), Zero);
882 MVT ResTy =
N->getValueType(0).getSimpleVT();
884 MVT OpTy =
N->getOperand(0).getValueType().getSimpleVT(); (void)OpTy;
896 MVT ResTy =
N->getValueType(0).getSimpleVT();
911 Ops = {
N->getOperand(0),
N->getOperand(1)};
932 Hexagon::A2_andir, dl, MVT::f32,
SDValue(n, 0),
938 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
950 std::array<SDValue, 4> temp1 = {
SDValue(NNewQ, 0),
SDValue(NqErr, 0),
962 Ops = {
N->getOperand(0),
N->getOperand(1)};
984 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
987 Hexagon::F2_sfmpy, dl, MVT::f32,
SDValue(NNewRec, 0),
SDValue(n, 0));
992 if (
N->getFlags().hasAllowReassociation())
1000 if (
N->isMachineOpcode())
1001 return N->setNodeId(-1);
1003 auto isHvxOp = [
this](
SDNode *
N) {
1004 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
1016 switch (
N->getOpcode()) {
1024 switch (
N->getOpcode()) {
1053 std::vector<SDValue> &OutOps) {
1056 switch (ConstraintID) {
1063 OutOps.push_back(Res);
1065 OutOps.push_back(Inp);
1078 if (!U->hasOneUse())
1080 unsigned Opc = U->getOpcode();
1091 SDValue S0 = U->getOperand(0);
1095 SDNode *UUse = *U->use_begin();
1103 SDNode *SYNode = SY.getNode();
1105 SDValue LDBasePtr = cast<MemSDNode>(SYNode)->getBasePtr();
1106 SDValue STBasePtr = cast<MemSDNode>(UUse)->getBasePtr();
1107 if (LDBasePtr == STBasePtr)
1116void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {
1119 for (
auto *
I : Nodes) {
1123 auto IsSelect0 = [](
const SDValue &
Op) ->
bool {
1130 SDValue N0 =
I->getOperand(0), N1 =
I->getOperand(1);
1131 EVT VT =
I->getValueType(0);
1132 bool SelN0 = IsSelect0(N0);
1133 SDValue SOp = SelN0 ? N0 : N1;
1134 SDValue VOp = SelN0 ? N1 : N0;
1160void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {
1163 for (
auto *
I : Nodes) {
1195 if (EV % (1 << CV) != 0)
1197 unsigned DV = EV / (1 << CV);
1224void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {
1228 unsigned Opc =
N->getOpcode();
1265 if (TZ +
M1 + LZ != 32)
1289void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {
1293 unsigned Opc =
N->getOpcode();
1300 for (
auto I =
N->use_begin(),
E =
N->use_end();
I !=
E; ++
I) {
1302 if (
U->getNumValues() != 1)
1304 EVT UVT =
U->getValueType(0);
1314 unsigned I1N =
I.getOperandNo();
1316 for (
unsigned i = 0, n =
U->getNumOperands(); i != n; ++i)
1317 Ops[i] =
U->getOperand(i);
1318 EVT BVT = Ops[I1N].getValueType();
1325 if (isa<MachineSDNode>(U)) {
1326 unsigned UseOpc =
U->getMachineOpcode();
1332 unsigned UseOpc =
U->getOpcode();
1334 If0 = DAG.
getNode(UseOpc, dl, UVT, Ops);
1336 If1 = DAG.
getNode(UseOpc, dl, UVT, Ops);
1354 auto getNodes = [
this]() -> std::vector<SDNode *> {
1355 std::vector<SDNode *>
T;
1363 PreprocessHvxISelDAG();
1367 ppSimplifyOrSelect0(getNodes());
1375 ppAddrReorderAddShl(getNodes());
1390 ppAddrRewriteAndSrl(getNodes());
1394 ppHoistZextI1(getNodes());
1397 dbgs() <<
"Preprocessed (Hexagon) selection DAG:";
1402 rebalanceAddressTrees();
1405 dbgs() <<
"Address tree balanced selection DAG:";
1414 if (!HFI.needsAligna(*
MF))
1431 assert(AP.
isValid() &&
"Couldn't reserve stack align register");
1437void HexagonDAGToDAGISel::updateAligna() {
1439 if (!HFI.needsAligna(*
MF))
1441 auto *AlignaI =
const_cast<MachineInstr*
>(HFI.getAlignaInstr(*
MF));
1442 assert(AlignaI !=
nullptr);
1444 if (AlignaI->getOperand(1).getImm() < MaxA)
1445 AlignaI->getOperand(1).setImm(MaxA);
1454 int FX = cast<FrameIndexSDNode>(
N)->getIndex();
1487 EVT T =
N.getValueType();
1488 if (!
T.isInteger() ||
T.getSizeInBits() != 32 || !isa<ConstantSDNode>(
N))
1490 int32_t V = cast<const ConstantSDNode>(
N)->getZExtValue();
1497 switch (
N.getOpcode()) {
1499 if (
N.getValueType() != MVT::i32)
1501 int32_t V = cast<const ConstantSDNode>(
N)->getZExtValue();
1510 if (Alignment >
Align(8))
1512 R =
N.getOperand(0);
1516 if (Alignment >
Align(1))
1522 if (Alignment >
Align(4) ||
1537 bool UseGP,
Align Alignment) {
1538 switch (
N.getOpcode()) {
1548 if (!
isAligned(Alignment, Const->getZExtValue()))
1555 N.getValueType(), NewOff);
1568 R =
N.getOperand(0);
1572 R =
N.getOperand(0);
1600 if (
N.getValueType() != MVT::i64)
1602 unsigned Opc =
N.getOpcode();
1608 ?
N.getOperand(0).getValueType()
1609 : cast<VTSDNode>(
N.getOperand(1))->getVT();
1610 unsigned SW =
T.getSizeInBits();
1612 R =
N.getOperand(0);
1625 if (L->getMemoryVT().getSizeInBits() > 32)
1631 auto *S = dyn_cast<ConstantSDNode>(
N.getOperand(1));
1632 if (!S || S->getZExtValue() != 32)
1640 EVT RT = R.getValueType();
1658bool HexagonDAGToDAGISel::keepsLowBits(
const SDValue &Val,
unsigned NumBits,
1667 if (
T.isInteger() &&
T.getSizeInBits() == NumBits) {
1678 if (
T->getVT().getSizeInBits() == NumBits) {
1688 if (
C->getZExtValue() ==
Mask) {
1694 if (
C->getZExtValue() ==
Mask) {
1706 if ((
C->getZExtValue() &
Mask) == 0) {
1712 if ((
C->getZExtValue() &
Mask) == 0) {
1725bool HexagonDAGToDAGISel::isAlignedMemNode(
const MemSDNode *
N)
const {
1726 return N->getAlign().value() >=
N->getMemoryVT().getStoreSize();
1729bool HexagonDAGToDAGISel::isSmallStackStore(
const StoreSDNode *
N)
const {
1731 switch (
N->getMemoryVT().getStoreSize()) {
1733 return StackSize <= 56;
1735 return StackSize <= 120;
1737 return StackSize <= 248;
1744bool HexagonDAGToDAGISel::isPositiveHalfWord(
const SDNode *
N)
const {
1747 return V > 0 && isInt<16>(V);
1750 const VTSDNode *VN = dyn_cast<const VTSDNode>(
N->getOperand(1));
1756bool HexagonDAGToDAGISel::hasOneUse(
const SDNode *
N)
const {
1764 switch (
N->getOpcode()) {
1771 return isa<ConstantSDNode>(
N->getOperand(1).getNode());
1778int HexagonDAGToDAGISel::getWeight(
SDNode *
N) {
1781 assert(RootWeights.count(
N) &&
"Cannot get weight of unseen root!");
1782 assert(RootWeights[
N] != -1 &&
"Cannot get weight of unvisited root!");
1783 assert(RootWeights[
N] != -2 &&
"Cannot get weight of RAWU'd root!");
1784 return RootWeights[
N];
1787int HexagonDAGToDAGISel::getHeight(
SDNode *
N) {
1790 assert(RootWeights.count(
N) && RootWeights[
N] >= 0 &&
1791 "Cannot query height of unvisited/RAUW'd node!");
1792 return RootHeights[
N];
1796struct WeightedLeaf {
1803 WeightedLeaf(
SDValue Value,
int Weight,
int InsertionOrder) :
1804 Value(
Value), Weight(Weight), InsertionOrder(InsertionOrder) {
1805 assert(Weight >= 0 &&
"Weight must be >= 0");
1808 static bool Compare(
const WeightedLeaf &
A,
const WeightedLeaf &
B) {
1809 assert(
A.Value.getNode() &&
B.Value.getNode());
1810 return A.Weight ==
B.Weight ?
1811 (
A.InsertionOrder >
B.InsertionOrder) :
1812 (
A.Weight >
B.Weight);
1819class LeafPrioQueue {
1822 WeightedLeaf ConstElt;
1827 return (!HaveConst && Q.
empty());
1831 return Q.
size() + HaveConst;
1838 const WeightedLeaf &top() {
1844 WeightedLeaf pop() {
1849 std::pop_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1853 void push(WeightedLeaf L,
bool SeparateConst=
true) {
1854 if (!HaveConst && SeparateConst && isa<ConstantSDNode>(
L.Value)) {
1856 cast<ConstantSDNode>(
L.Value)->getSExtValue() == 1)
1859 cast<ConstantSDNode>(
L.Value)->getSExtValue() == 0)
1866 std::push_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1872 void pushToBottom(WeightedLeaf L) {
1879 WeightedLeaf findSHL(
uint64_t MaxAmount);
1881 WeightedLeaf findMULbyConst();
1883 LeafPrioQueue(
unsigned Opcode) :
1884 HaveConst(
false), Opcode(Opcode) { }
1888WeightedLeaf LeafPrioQueue::findSHL(
uint64_t MaxAmount) {
1892 for (
int Pos = 0,
End = Q.
size(); Pos !=
End; ++Pos) {
1893 const WeightedLeaf &
L = Q[Pos];
1900 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1907 if (
Result.Value.getNode()) {
1908 Q.
erase(&Q[ResultPos]);
1909 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1915WeightedLeaf LeafPrioQueue::findMULbyConst() {
1919 for (
int Pos = 0,
End = Q.
size(); Pos !=
End; ++Pos) {
1920 const WeightedLeaf &
L = Q[Pos];
1927 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1934 if (
Result.Value.getNode()) {
1935 Q.
erase(&Q[ResultPos]);
1936 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1943 uint64_t MulFactor = 1ull <<
N->getConstantOperandVal(1);
1945 N->getOperand(1).getValueType());
1951 unsigned MaxFactor = 0;
1952 for (
int i = 0; i < 2; ++i) {
1956 const APInt &CInt =
C->getAPIntValue();
1974 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
1975 for (
int i = 0; i < 2; ++i)
1976 if (isa<ConstantSDNode>(Ops[i].getNode()) &&
1977 V.getConstantOperandVal(i) % (1ULL << Amount) == 0) {
1978 uint64_t NewConst = V.getConstantOperandVal(i) >> Amount;
1979 return (NewConst == 1);
1981 }
else if (V.getOpcode() ==
ISD::SHL) {
1982 return (Amount == V.getConstantOperandVal(1));
1988SDValue HexagonDAGToDAGISel::factorOutPowerOf2(
SDValue V,
unsigned Power) {
1989 SDValue Ops[] = {
V.getOperand(0),
V.getOperand(1) };
1991 for (
int i=0; i < 2; ++i) {
1992 if (isa<ConstantSDNode>(Ops[i].getNode()) &&
1993 V.getConstantOperandVal(i) % ((
uint64_t)1 << Power) == 0) {
1994 uint64_t NewConst =
V.getConstantOperandVal(i) >> Power;
1998 SDLoc(V),
V.getValueType());
2003 uint64_t ShiftAmount =
V.getConstantOperandVal(1);
2004 if (ShiftAmount == Power)
2007 SDLoc(V),
V.getValueType());
2018unsigned HexagonDAGToDAGISel::getUsesInFunction(
const Value *V) {
2019 if (GAUsesInFunction.count(V))
2020 return GAUsesInFunction[
V];
2024 for (
const User *U :
V->users()) {
2025 if (isa<Instruction>(U) &&
2040SDValue HexagonDAGToDAGISel::balanceSubTree(
SDNode *
N,
bool TopLevel) {
2041 assert(RootWeights.count(
N) &&
"Cannot balance non-root node.");
2042 assert(RootWeights[
N] != -2 &&
"This node was RAUW'd!");
2046 if (RootWeights[
N] != -1)
2060 Weight = getWeight(balanceSubTree(Op0N).getNode());
2063 Weight = getWeight(Op0N);
2065 SDNode *Op1N =
N->getOperand(1).getNode();
2067 Weight += getWeight(balanceSubTree(Op1N).getNode());
2070 Weight += getWeight(Op1N);
2072 RootWeights[
N] = Weight;
2073 RootHeights[
N] = std::max(getHeight(
N->getOperand(0).getNode()),
2074 getHeight(
N->getOperand(1).getNode())) + 1;
2076 LLVM_DEBUG(
dbgs() <<
"--> No need to balance root (Weight=" << Weight
2077 <<
" Height=" << RootHeights[
N] <<
"): ");
2086 unsigned NOpcode =
N->getOpcode();
2088 LeafPrioQueue Leaves(NOpcode);
2096 bool CanFactorize =
false;
2097 WeightedLeaf Mul1, Mul2;
2098 unsigned MaxPowerOf2 = 0;
2103 bool HaveTopLevelShift =
false;
2109 HaveTopLevelShift =
true;
2113 int InsertionOrder = 0;
2115 bool Imbalanced =
false;
2116 int CurrentWeight = 0;
2117 while (!Worklist.
empty()) {
2123 int Weight = RootWeights[Child.
getNode()];
2125 Child = balanceSubTree(Child.
getNode());
2127 Weight = getWeight(Child.
getNode());
2128 }
else if (Weight == -2) {
2133 return balanceSubTree(
N, TopLevel);
2136 NodeHeights[Child] = 1;
2137 CurrentWeight += Weight;
2140 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&
2146 if (!Mul1.Value.getNode()) {
2147 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);
2148 MaxPowerOf2 = PowerOf2;
2150 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);
2151 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);
2154 if (MaxPowerOf2 > 3)
2157 CanFactorize =
true;
2160 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2163 int Weight = getWeight(Child.
getNode());
2165 NodeHeights[Child] = getHeight(Child.
getNode());
2166 CurrentWeight += Weight;
2169 GA = WeightedLeaf(Child, Weight, InsertionOrder++);
2171 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2175 unsigned ChildOpcode = Child.
getOpcode();
2176 assert(ChildOpcode == NOpcode ||
2182 Op1 = getMultiplierForSHL(Child.
getNode());
2187 assert(!NodeHeights.
count(Child) &&
"Parent visited before children?");
2194 if (std::abs(NodeHeights[Op1] - NodeHeights[Child->
getOperand(0)]) > 1)
2197 NodeHeights[Child] = std::max(NodeHeights[Op1],
2204 <<
" weight=" << CurrentWeight
2205 <<
" imbalanced=" << Imbalanced <<
"\n");
2211 LLVM_DEBUG(
dbgs() <<
"--> Found common factor for two MUL children!\n");
2212 int Weight = Mul1.Weight + Mul2.Weight;
2213 int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;
2214 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);
2215 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);
2217 Mul1Factored, Mul2Factored);
2219 Mul1.Value.getValueType());
2222 NodeHeights[
New] = Height;
2223 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));
2224 }
else if (Mul1.Value.getNode()) {
2228 if (Mul2.Value.getNode())
2230 CanFactorize =
false;
2236 bool CombinedGA =
false;
2237 if (NOpcode ==
ISD::ADD && GA.Value.getNode() && Leaves.hasConst() &&
2238 GA.Value.hasOneUse() &&
N->use_size() < 3) {
2240 cast<GlobalAddressSDNode>(GA.Value.getOperand(0));
2243 if (getUsesInFunction(GANode->
getGlobal()) == 1 &&
Offset->hasOneUse() &&
2246 <<
Offset->getSExtValue() <<
"): ");
2254 GA.Value.getValueType(), NewTGA);
2255 GA.Weight += Leaves.top().Weight;
2257 NodeHeights[GA.Value] = getHeight(GA.Value.getNode());
2266 RootWeights[
N] = CurrentWeight;
2267 RootHeights[
N] = NodeHeights[
SDValue(
N, 0)];
2273 if (NOpcode ==
ISD::ADD && GA.Value.getNode()) {
2274 WeightedLeaf
SHL = Leaves.findSHL(31);
2275 if (
SHL.Value.getNode()) {
2276 int Height = std::max(NodeHeights[GA.Value], NodeHeights[
SHL.Value]) + 1;
2278 GA.Value.getValueType(),
2279 GA.Value,
SHL.Value);
2280 GA.Weight =
SHL.Weight;
2281 NodeHeights[GA.Value] = Height;
2285 if (GA.Value.getNode())
2290 if (TopLevel && !CanFactorize && Leaves.hasConst()) {
2292 Leaves.pushToBottom(Leaves.pop());
2299 while (Leaves.size() > 1) {
2300 WeightedLeaf L0 = Leaves.pop();
2304 WeightedLeaf L1 = Leaves.findMULbyConst();
2305 if (!L1.Value.getNode())
2308 assert(L0.Weight <= L1.Weight &&
"Priority queue is broken!");
2311 int V0Weight = L0.Weight;
2313 int V1Weight = L1.Weight;
2316 if ((RootWeights.count(V0.
getNode()) && RootWeights[V0.
getNode()] == -2) ||
2317 (RootWeights.count(V1.
getNode()) && RootWeights[V1.
getNode()] == -2)) {
2319 return balanceSubTree(
N, TopLevel);
2324 EVT VT =
N->getValueType(0);
2334 "Children must have been visited before re-combining them!");
2335 int Height = std::max(NodeHeights[V0], NodeHeights[V1]) + 1;
2347 NodeHeights[NewNode] = Height;
2349 int Weight = V0Weight + V1Weight;
2350 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));
2353 <<
",Height=" << Height <<
"):\n");
2357 assert(Leaves.size() == 1);
2358 SDValue NewRoot = Leaves.top().Value;
2361 int Height = NodeHeights[NewRoot];
2384 RootWeights[
N] = -2;
2389 RootWeights[NewRoot.
getNode()] = Leaves.top().Weight;
2390 RootHeights[NewRoot.
getNode()] = Height;
2395void HexagonDAGToDAGISel::rebalanceAddressTrees() {
2406 if (RootWeights.count(
BasePtr.getNode()))
2409 LLVM_DEBUG(
dbgs() <<
"** Rebalancing address calculation in node: ");
2418 while (!Worklist.
empty()) {
2420 unsigned Opcode =
N->getOpcode();
2425 Worklist.
push_back(
N->getOperand(0).getNode());
2426 Worklist.
push_back(
N->getOperand(1).getNode());
2429 if (
N->hasOneUse() && Opcode ==
N->use_begin()->getOpcode())
2433 if (RootWeights.count(
N))
2436 RootWeights[
N] = -1;
2440 RootWeights[
BasePtr.getNode()] = -1;
2445 NewBasePtr,
N->getOperand(2));
2448 NewBasePtr,
N->getOperand(3));
2455 GAUsesInFunction.clear();
2456 RootHeights.clear();
2457 RootWeights.clear();
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const Function * getParent(const Value *V)
BlockVerifier::State From
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 GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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
#define DEBUG_WITH_TYPE(TYPE, X)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static bool willShiftRightEliminate(SDValue V, unsigned Amount)
static cl::opt< bool > RebalanceOnlyImbalancedTrees("rebalance-only-imbal", cl::Hidden, cl::init(false), cl::desc("Rebalance address tree only if it is imbalanced"))
static unsigned getPowerOf2Factor(SDValue Val)
static cl::opt< bool > CheckSingleUse("hexagon-isel-su", cl::Hidden, cl::init(true), cl::desc("Enable checking of SDNode's single-use status"))
static cl::opt< bool > EnableAddressRebalancing("isel-rebalance-addr", cl::Hidden, cl::init(true), cl::desc("Rebalance address calculation trees to improve " "instruction selection"))
static bool isMemOPCandidate(SDNode *I, SDNode *U)
static bool isTargetConstant(const SDValue &V)
static bool isOpcodeHandled(const SDNode *N)
static cl::opt< bool > RebalanceOnlyForOptimizations("rebalance-only-opt", cl::Hidden, cl::init(false), cl::desc("Rebalance address tree only if this allows optimizations"))
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Class for arbitrary precision integers.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned logBase2() const
bool getBoolValue() const
Convert APInt to a boolean value.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
FunctionPass class - This class is used to implement most global optimizations.
int64_t getOffset() const
const GlobalValue * getGlobal() const
This class is used to form a handle around another node that is persistent and is updated across invo...
const SDValue & getValue() const
void SelectAddSubCarry(SDNode *N)
void SelectConstant(SDNode *N)
void SelectIntrinsicWOChain(SDNode *N)
void Select(SDNode *N) override
Main hook for targets to transform nodes into machine nodes.
bool SelectNewCircIntrinsic(SDNode *IntN)
Generate a machine instruction node for the new circular buffer intrinsics.
bool tryLoadOfLoadIntrinsic(LoadSDNode *N)
void SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl)
void SelectExtractSubvector(SDNode *N)
void SelectVAlign(SDNode *N)
MachineSDNode * LoadInstrForLoadIntrinsic(SDNode *IntN)
bool SelectAnyImm2(SDValue &N, SDValue &R)
bool SelectAnyImm(SDValue &N, SDValue &R)
void SelectV65GatherPred(SDNode *N)
bool SelectAnyImm0(SDValue &N, SDValue &R)
void SelectSHL(SDNode *N)
void SelectIntrinsicWChain(SDNode *N)
void SelectV2Q(SDNode *N)
bool SelectAnyImm1(SDValue &N, SDValue &R)
void SelectConstantFP(SDNode *N)
bool DetectUseSxtw(SDValue &N, SDValue &R)
bool SelectBrevLdIntrinsic(SDNode *IntN)
void emitFunctionEntryCode() override
bool SelectAddrFI(SDValue &N, SDValue &R)
SDNode * StoreInstrForLoadIntrinsic(MachineSDNode *LoadN, SDNode *IntN)
bool SelectAddrGP(SDValue &N, SDValue &R)
bool SelectAnyImmediate(SDValue &N, SDValue &R, Align Alignment)
bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP, Align Alignment)
void SelectFrameIndex(SDNode *N)
bool SelectAnyImm3(SDValue &N, SDValue &R)
void SelectFDiv(SDNode *N)
void SelectStore(SDNode *N)
void SelectLoad(SDNode *N)
bool SelectAnyInt(SDValue &N, SDValue &R)
bool SelectAddrGA(SDValue &N, SDValue &R)
void PreprocessISelDAG() override
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
void SelectTypecast(SDNode *N)
void SelectD2P(SDNode *N)
void SelectVAlignAddr(SDNode *N)
void SelectP2D(SDNode *N)
bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps) override
SelectInlineAsmMemoryOperand - Implement addressing mode selection for inline asm expressions.
void SelectV65Gather(SDNode *N)
void SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl)
void SelectHVXDualOutput(SDNode *N)
void SelectQ2V(SDNode *N)
bool isValidAutoIncImm(const EVT VT, const int Offset) const
Hexagon target-specific information for each MachineFunction.
BitVector getReservedRegs(const MachineFunction &MF) const override
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
const HexagonFrameLowering * getFrameLowering() const override
const HexagonRegisterInfo * getRegisterInfo() const override
bool isHVXVectorType(EVT VecTy, bool IncludeBool=false) const
unsigned getVectorLength() const
This class is used to represent ISD::LOAD nodes.
unsigned getVectorNumElements() const
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
MVT getVectorElementType() const
static MVT getIntegerVT(unsigned BitWidth)
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
uint64_t estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
A description of a memory reference used in the backend.
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
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.
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.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
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.
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
const TargetLowering * TLI
void ReplaceUses(SDValue F, SDValue T)
ReplaceUses - replace all uses of the old node F with the use of the new node T.
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
const TargetLowering * getTargetLowering() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
SDNode * MorphNodeTo(SDNode *N, unsigned Opc, SDVTList VTs, ArrayRef< SDValue > Ops)
This mutates the specified node to have the specified return type, opcode, and operands.
SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
const DataLayout & getDataLayout() const
SDValue getTargetFrameIndex(int FI, EVT VT)
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
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 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.
void RemoveDeadNodes()
This method deletes all unreachable nodes in the SelectionDAG.
void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
iterator_range< allnodes_iterator > allnodes()
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
ilist< SDNode >::size_type allnodes_size() const
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
MachineFunction & getMachineFunction() const
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
iterator erase(const_iterator CI)
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.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
virtual MVT getScalarShiftAmountTy(const DataLayout &, EVT) const
Return the type to use for a scalar shift opcode, given the shifted amount type.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
This class is used to represent EVT's, which are used to parameterize some operations.
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
@ C
The default llvm calling convention, compatible with C.
@ 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...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ SIGN_EXTEND
Conversion operators.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ 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.
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
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.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
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)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
CodeGenOptLevel
Code generation optimization level.
FunctionPass * createHexagonISelDag(HexagonTargetMachine &TM, CodeGenOptLevel OptLevel)
createHexagonISelDag - This pass converts a legalized DAG into a Hexagon-specific DAG,...
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
@ Default
The result values are uniform if and only if all operands are uniform.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
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.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isVector() const
Return true if this is a vector value type.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isInteger() const
Return true if this is an integer or a vector integer type.
This class contains a discriminated union of information about pointers in memory operands,...
This represents a list of ValueType's that has been intern'd by a SelectionDAG.