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"
80 int32_t Inc = cast<ConstantSDNode>(
Offset.getNode())->getSExtValue();
81 EVT LoadedVT = LD->getMemoryVT();
88 bool IsValidInc = HII->isValidAutoIncImm(LoadedVT, Inc);
94 Opcode = IsValidInc ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrub_io;
96 Opcode = IsValidInc ? Hexagon::L2_loadrb_pi : Hexagon::L2_loadrb_io;
100 Opcode = IsValidInc ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadruh_io;
102 Opcode = IsValidInc ? Hexagon::L2_loadrh_pi : Hexagon::L2_loadrh_io;
108 Opcode = IsValidInc ? Hexagon::L2_loadri_pi : Hexagon::L2_loadri_io;
115 Opcode = IsValidInc ? Hexagon::L2_loadrd_pi : Hexagon::L2_loadrd_io;
125 if (isAlignedMemNode(LD)) {
126 if (LD->isNonTemporal())
127 Opcode = IsValidInc ? Hexagon::V6_vL32b_nt_pi : Hexagon::V6_vL32b_nt_ai;
129 Opcode = IsValidInc ? Hexagon::V6_vL32b_pi : Hexagon::V6_vL32b_ai;
131 Opcode = IsValidInc ? Hexagon::V6_vL32Ub_pi : Hexagon::V6_vL32Ub_ai;
138 SDValue IncV = CurDAG->getTargetConstant(Inc, dl, MVT::i32);
144 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
145 return CurDAG->getMachineNode(Hexagon::A4_combineir, dl, MVT::i64,
149 return CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
158 EVT ValueVT = LD->getValueType(0);
167 MachineSDNode *L = CurDAG->getMachineNode(Opcode, dl, ValueVT,
168 MVT::i32, MVT::Other,
Base,
170 CurDAG->setNodeMemRefs(L, {
MemOp});
174 if (LD->getValueType(0) == MVT::i64)
178 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
179 MachineSDNode *L = CurDAG->getMachineNode(Opcode, dl, ValueVT, MVT::Other,
181 CurDAG->setNodeMemRefs(L, {
MemOp});
183 MachineSDNode *
A = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
187 if (LD->getValueType(0) == MVT::i64)
191 ReplaceUses(
From, To, 3);
192 CurDAG->RemoveDeadNode(LD);
202 static std::map<unsigned,unsigned> LoadPciMap = {
203 { Intrinsic::hexagon_circ_ldb, Hexagon::L2_loadrb_pci },
204 { Intrinsic::hexagon_circ_ldub, Hexagon::L2_loadrub_pci },
205 { Intrinsic::hexagon_circ_ldh, Hexagon::L2_loadrh_pci },
206 { Intrinsic::hexagon_circ_lduh, Hexagon::L2_loadruh_pci },
207 { Intrinsic::hexagon_circ_ldw, Hexagon::L2_loadri_pci },
208 { Intrinsic::hexagon_circ_ldd, Hexagon::L2_loadrd_pci },
210 auto FLC = LoadPciMap.find(IntNo);
211 if (FLC != LoadPciMap.end()) {
212 EVT ValTy = (IntNo == Intrinsic::hexagon_circ_ldd) ? MVT::i64 : MVT::i32;
213 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
215 auto Inc = cast<ConstantSDNode>(IntN->
getOperand(5));
218 { IntN->getOperand(2), I, IntN->getOperand(4),
219 IntN->getOperand(0) });
234 unsigned Size = 1U << (SizeBits-1);
292 switch (
C->getConstantOperandVal(1)) {
293 case Intrinsic::hexagon_circ_ldub:
294 case Intrinsic::hexagon_circ_lduh:
297 case Intrinsic::hexagon_circ_ldw:
298 case Intrinsic::hexagon_circ_ldd:
305 if (
N->getExtensionType() != IntExt)
310 if (
C->getNumOperands() < 4 || Loc.
getNode() !=
C->getOperand(3).getNode())
332 const SDLoc &dl(IntN);
335 static const std::map<unsigned, unsigned> LoadBrevMap = {
336 { Intrinsic::hexagon_L2_loadrb_pbr, Hexagon::L2_loadrb_pbr },
337 { Intrinsic::hexagon_L2_loadrub_pbr, Hexagon::L2_loadrub_pbr },
338 { Intrinsic::hexagon_L2_loadrh_pbr, Hexagon::L2_loadrh_pbr },
339 { Intrinsic::hexagon_L2_loadruh_pbr, Hexagon::L2_loadruh_pbr },
340 { Intrinsic::hexagon_L2_loadri_pbr, Hexagon::L2_loadri_pbr },
341 { Intrinsic::hexagon_L2_loadrd_pbr, Hexagon::L2_loadrd_pbr }
343 auto FLI = LoadBrevMap.find(IntNo);
344 if (FLI != LoadBrevMap.end()) {
346 (IntNo == Intrinsic::hexagon_L2_loadrd_pbr) ? MVT::i64 : MVT::i32;
347 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
352 FLI->second, dl, RTys,
377 static std::map<unsigned,unsigned> LoadNPcMap = {
378 { Intrinsic::hexagon_L2_loadrub_pci, Hexagon::PS_loadrub_pci },
379 { Intrinsic::hexagon_L2_loadrb_pci, Hexagon::PS_loadrb_pci },
380 { Intrinsic::hexagon_L2_loadruh_pci, Hexagon::PS_loadruh_pci },
381 { Intrinsic::hexagon_L2_loadrh_pci, Hexagon::PS_loadrh_pci },
382 { Intrinsic::hexagon_L2_loadri_pci, Hexagon::PS_loadri_pci },
383 { Intrinsic::hexagon_L2_loadrd_pci, Hexagon::PS_loadrd_pci },
384 { Intrinsic::hexagon_L2_loadrub_pcr, Hexagon::PS_loadrub_pcr },
385 { Intrinsic::hexagon_L2_loadrb_pcr, Hexagon::PS_loadrb_pcr },
386 { Intrinsic::hexagon_L2_loadruh_pcr, Hexagon::PS_loadruh_pcr },
387 { Intrinsic::hexagon_L2_loadrh_pcr, Hexagon::PS_loadrh_pcr },
388 { Intrinsic::hexagon_L2_loadri_pcr, Hexagon::PS_loadri_pcr },
389 { Intrinsic::hexagon_L2_loadrd_pcr, Hexagon::PS_loadrd_pcr }
391 auto FLI = LoadNPcMap.find (IntNo);
392 if (FLI != LoadNPcMap.end()) {
393 EVT ValTy = MVT::i32;
394 if (IntNo == Intrinsic::hexagon_L2_loadrd_pci ||
395 IntNo == Intrinsic::hexagon_L2_loadrd_pcr)
397 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
400 auto Inc = cast<ConstantSDNode>(IntN->
getOperand(3));
418 static std::map<unsigned,unsigned> StoreNPcMap = {
419 { Intrinsic::hexagon_S2_storerb_pci, Hexagon::PS_storerb_pci },
420 { Intrinsic::hexagon_S2_storerh_pci, Hexagon::PS_storerh_pci },
421 { Intrinsic::hexagon_S2_storerf_pci, Hexagon::PS_storerf_pci },
422 { Intrinsic::hexagon_S2_storeri_pci, Hexagon::PS_storeri_pci },
423 { Intrinsic::hexagon_S2_storerd_pci, Hexagon::PS_storerd_pci },
424 { Intrinsic::hexagon_S2_storerb_pcr, Hexagon::PS_storerb_pcr },
425 { Intrinsic::hexagon_S2_storerh_pcr, Hexagon::PS_storerh_pcr },
426 { Intrinsic::hexagon_S2_storerf_pcr, Hexagon::PS_storerf_pcr },
427 { Intrinsic::hexagon_S2_storeri_pcr, Hexagon::PS_storeri_pcr },
428 { Intrinsic::hexagon_S2_storerd_pcr, Hexagon::PS_storerd_pcr }
430 auto FSI = StoreNPcMap.find (IntNo);
431 if (FSI != StoreNPcMap.end()) {
432 EVT RTys[] = { MVT::i32, MVT::Other };
435 auto Inc = cast<ConstantSDNode>(IntN->
getOperand(3));
474 SDValue Chain = ST->getChain();
479 int32_t Inc = cast<ConstantSDNode>(
Offset.getNode())->getSExtValue();
480 EVT StoredVT = ST->getMemoryVT();
489 Opcode = IsValidInc ? Hexagon::S2_storerb_pi : Hexagon::S2_storerb_io;
492 Opcode = IsValidInc ? Hexagon::S2_storerh_pi : Hexagon::S2_storerh_io;
498 Opcode = IsValidInc ? Hexagon::S2_storeri_pi : Hexagon::S2_storeri_io;
505 Opcode = IsValidInc ? Hexagon::S2_storerd_pi : Hexagon::S2_storerd_io;
515 if (isAlignedMemNode(ST)) {
516 if (ST->isNonTemporal())
517 Opcode = IsValidInc ? Hexagon::V6_vS32b_nt_pi : Hexagon::V6_vS32b_nt_ai;
519 Opcode = IsValidInc ? Hexagon::V6_vS32b_pi : Hexagon::V6_vS32b_ai;
521 Opcode = IsValidInc ? Hexagon::V6_vS32Ub_pi : Hexagon::V6_vS32Ub_ai;
528 if (ST->isTruncatingStore() && ValueVT.
getSizeInBits() == 64) {
531 dl, MVT::i32,
Value);
583 auto Default = [
this,
N] () ->
void { SelectCode(
N); };
589 int32_t ShlConst = cast<ConstantSDNode>(Shl_1)->getSExtValue();
596 int32_t ValConst =
C->getSExtValue() << ShlConst;
597 if (isInt<9>(ValConst)) {
600 MVT::i32, Mul_0, Val);
617 int32_t ValConst = 1 << (ShlConst + C2->getSExtValue());
618 if (isInt<9>(-ValConst)) {
621 MVT::i32, Shl2_0, Val);
649 unsigned IntNo =
N->getConstantOperandVal(1);
650 if (IntNo == Intrinsic::hexagon_V6_vgathermw ||
651 IntNo == Intrinsic::hexagon_V6_vgathermw_128B ||
652 IntNo == Intrinsic::hexagon_V6_vgathermh ||
653 IntNo == Intrinsic::hexagon_V6_vgathermh_128B ||
654 IntNo == Intrinsic::hexagon_V6_vgathermhw ||
655 IntNo == Intrinsic::hexagon_V6_vgathermhw_128B) {
659 if (IntNo == Intrinsic::hexagon_V6_vgathermwq ||
660 IntNo == Intrinsic::hexagon_V6_vgathermwq_128B ||
661 IntNo == Intrinsic::hexagon_V6_vgathermhq ||
662 IntNo == Intrinsic::hexagon_V6_vgathermhq_128B ||
663 IntNo == Intrinsic::hexagon_V6_vgathermhwq ||
664 IntNo == Intrinsic::hexagon_V6_vgathermhwq_128B) {
673 unsigned IID =
N->getConstantOperandVal(0);
676 case Intrinsic::hexagon_S2_vsplatrb:
679 case Intrinsic::hexagon_S2_vsplatrh:
682 case Intrinsic::hexagon_V6_vaddcarry:
683 case Intrinsic::hexagon_V6_vaddcarry_128B:
684 case Intrinsic::hexagon_V6_vsubcarry:
685 case Intrinsic::hexagon_V6_vsubcarry_128B:
696 if (keepsLowBits(V, Bits, U)) {
698 N->getOperand(0), U);
700 SelectCode(R.getNode());
708 MVT ResTy =
N->getValueType(0).getSimpleVT();
709 unsigned Idx =
N->getConstantOperandVal(1);
718 unsigned SubReg =
Idx == 0 ? Hexagon::isub_lo : Hexagon::isub_hi;
729 auto *CN = cast<ConstantFPSDNode>(
N);
730 APInt A = CN->getValueAPF().bitcastToAPInt();
731 if (
N->getValueType(0) == MVT::f32) {
736 if (
N->getValueType(0) == MVT::f64) {
749 if (
N->getValueType(0) == MVT::i1) {
750 assert(!(
N->getAsZExtVal() >> 1));
751 unsigned Opc = (cast<ConstantSDNode>(
N)->getSExtValue() != 0)
764 int FX = cast<FrameIndexSDNode>(
N)->getIndex();
781 Register AR = HMFI.getStackAlignBaseReg();
792 : Hexagon::A4_subp_c;
794 { N->getOperand(0), N->getOperand(1),
800 MVT ResTy =
N->getValueType(0).getSimpleVT();
802 return SelectHvxVAlign(
N);
823 M0,
N->getOperand(2),
M1);
826 N->getOperand(2),
M1);
840 N->getOperand(0),
N->getOperand(1),
849 int Mask = -cast<ConstantSDNode>(
A.getNode())->getSExtValue();
854 N->getOperand(0), M);
863 MVT OpTy =
Op.getValueType().getSimpleVT();
870 MVT ResTy =
N->getValueType(0).getSimpleVT();
878 MVT ResTy =
N->getValueType(0).getSimpleVT();
881 N->getOperand(0), Zero);
887 MVT ResTy =
N->getValueType(0).getSimpleVT();
889 MVT OpTy =
N->getOperand(0).getValueType().getSimpleVT(); (void)OpTy;
901 MVT ResTy =
N->getValueType(0).getSimpleVT();
916 Ops = {
N->getOperand(0),
N->getOperand(1)};
937 Hexagon::A2_andir, dl, MVT::f32,
SDValue(n, 0),
943 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
955 std::array<SDValue, 4> temp1 = {
SDValue(NNewQ, 0),
SDValue(NqErr, 0),
967 Ops = {
N->getOperand(0),
N->getOperand(1)};
989 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
992 Hexagon::F2_sfmpy, dl, MVT::f32,
SDValue(NNewRec, 0),
SDValue(n, 0));
997 if (
N->getFlags().hasAllowReassociation())
1005 if (
N->isMachineOpcode())
1006 return N->setNodeId(-1);
1008 auto isHvxOp = [
this](
SDNode *
N) {
1009 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
1021 switch (
N->getOpcode()) {
1029 switch (
N->getOpcode()) {
1058 std::vector<SDValue> &OutOps) {
1061 switch (ConstraintID) {
1068 OutOps.push_back(Res);
1070 OutOps.push_back(Inp);
1083 if (!U->hasOneUse())
1085 unsigned Opc = U->getOpcode();
1096 SDValue S0 = U->getOperand(0);
1100 SDNode *UUse = *U->use_begin();
1108 SDNode *SYNode = SY.getNode();
1110 SDValue LDBasePtr = cast<MemSDNode>(SYNode)->getBasePtr();
1111 SDValue STBasePtr = cast<MemSDNode>(UUse)->getBasePtr();
1112 if (LDBasePtr == STBasePtr)
1121void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {
1124 for (
auto *
I : Nodes) {
1128 auto IsSelect0 = [](
const SDValue &
Op) ->
bool {
1135 SDValue N0 =
I->getOperand(0), N1 =
I->getOperand(1);
1136 EVT VT =
I->getValueType(0);
1137 bool SelN0 = IsSelect0(N0);
1138 SDValue SOp = SelN0 ? N0 : N1;
1139 SDValue VOp = SelN0 ? N1 : N0;
1165void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {
1168 for (
auto *
I : Nodes) {
1200 if (EV % (1 << CV) != 0)
1202 unsigned DV = EV / (1 << CV);
1229void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {
1233 unsigned Opc =
N->getOpcode();
1270 if (TZ +
M1 + LZ != 32)
1294void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {
1298 unsigned Opc =
N->getOpcode();
1305 for (
auto I =
N->use_begin(), E =
N->use_end();
I != E; ++
I) {
1307 if (
U->getNumValues() != 1)
1309 EVT UVT =
U->getValueType(0);
1319 unsigned I1N =
I.getOperandNo();
1321 for (
unsigned i = 0, n =
U->getNumOperands(); i != n; ++i)
1322 Ops[i] =
U->getOperand(i);
1323 EVT BVT = Ops[I1N].getValueType();
1330 if (isa<MachineSDNode>(U)) {
1331 unsigned UseOpc =
U->getMachineOpcode();
1337 unsigned UseOpc =
U->getOpcode();
1339 If0 = DAG.
getNode(UseOpc, dl, UVT, Ops);
1341 If1 = DAG.
getNode(UseOpc, dl, UVT, Ops);
1359 auto getNodes = [
this]() -> std::vector<SDNode *> {
1360 std::vector<SDNode *>
T;
1368 PreprocessHvxISelDAG();
1372 ppSimplifyOrSelect0(getNodes());
1380 ppAddrReorderAddShl(getNodes());
1395 ppAddrRewriteAndSrl(getNodes());
1399 ppHoistZextI1(getNodes());
1402 dbgs() <<
"Preprocessed (Hexagon) selection DAG:";
1407 rebalanceAddressTrees();
1410 dbgs() <<
"Address tree balanced selection DAG:";
1419 if (!HFI.needsAligna(*
MF))
1436 assert(AP.
isValid() &&
"Couldn't reserve stack align register");
1442void HexagonDAGToDAGISel::updateAligna() {
1444 if (!HFI.needsAligna(*
MF))
1446 auto *AlignaI =
const_cast<MachineInstr*
>(HFI.getAlignaInstr(*
MF));
1447 assert(AlignaI !=
nullptr);
1449 if (AlignaI->getOperand(1).getImm() < MaxA)
1450 AlignaI->getOperand(1).setImm(MaxA);
1459 int FX = cast<FrameIndexSDNode>(
N)->getIndex();
1492 EVT T =
N.getValueType();
1493 if (!
T.isInteger() ||
T.getSizeInBits() != 32 || !isa<ConstantSDNode>(
N))
1495 int32_t V = cast<const ConstantSDNode>(
N)->getZExtValue();
1502 switch (
N.getOpcode()) {
1504 if (
N.getValueType() != MVT::i32)
1506 int32_t V = cast<const ConstantSDNode>(
N)->getZExtValue();
1515 if (Alignment >
Align(8))
1517 R =
N.getOperand(0);
1521 if (Alignment >
Align(1))
1527 if (Alignment >
Align(4) ||
1542 bool UseGP,
Align Alignment) {
1543 switch (
N.getOpcode()) {
1553 if (!
isAligned(Alignment, Const->getZExtValue()))
1560 N.getValueType(), NewOff);
1573 R =
N.getOperand(0);
1577 R =
N.getOperand(0);
1605 if (
N.getValueType() != MVT::i64)
1607 unsigned Opc =
N.getOpcode();
1613 ?
N.getOperand(0).getValueType()
1614 : cast<VTSDNode>(
N.getOperand(1))->getVT();
1615 unsigned SW =
T.getSizeInBits();
1617 R =
N.getOperand(0);
1630 if (L->getMemoryVT().getSizeInBits() > 32)
1636 auto *S = dyn_cast<ConstantSDNode>(
N.getOperand(1));
1637 if (!S || S->getZExtValue() != 32)
1645 EVT RT = R.getValueType();
1663bool HexagonDAGToDAGISel::keepsLowBits(
const SDValue &Val,
unsigned NumBits,
1672 if (
T.isInteger() &&
T.getSizeInBits() == NumBits) {
1683 if (
T->getVT().getSizeInBits() == NumBits) {
1693 if (
C->getZExtValue() ==
Mask) {
1699 if (
C->getZExtValue() ==
Mask) {
1711 if ((
C->getZExtValue() &
Mask) == 0) {
1717 if ((
C->getZExtValue() &
Mask) == 0) {
1730bool HexagonDAGToDAGISel::isAlignedMemNode(
const MemSDNode *
N)
const {
1731 return N->getAlign().value() >=
N->getMemoryVT().getStoreSize();
1734bool HexagonDAGToDAGISel::isSmallStackStore(
const StoreSDNode *
N)
const {
1736 switch (
N->getMemoryVT().getStoreSize()) {
1738 return StackSize <= 56;
1740 return StackSize <= 120;
1742 return StackSize <= 248;
1749bool HexagonDAGToDAGISel::isPositiveHalfWord(
const SDNode *
N)
const {
1752 return V > 0 && isInt<16>(V);
1755 const VTSDNode *VN = dyn_cast<const VTSDNode>(
N->getOperand(1));
1761bool HexagonDAGToDAGISel::hasOneUse(
const SDNode *
N)
const {
1769 switch (
N->getOpcode()) {
1776 return isa<ConstantSDNode>(
N->getOperand(1).getNode());
1783int HexagonDAGToDAGISel::getWeight(
SDNode *
N) {
1786 assert(RootWeights.count(
N) &&
"Cannot get weight of unseen root!");
1787 assert(RootWeights[
N] != -1 &&
"Cannot get weight of unvisited root!");
1788 assert(RootWeights[
N] != -2 &&
"Cannot get weight of RAWU'd root!");
1789 return RootWeights[
N];
1792int HexagonDAGToDAGISel::getHeight(
SDNode *
N) {
1795 assert(RootWeights.count(
N) && RootWeights[
N] >= 0 &&
1796 "Cannot query height of unvisited/RAUW'd node!");
1797 return RootHeights[
N];
1801struct WeightedLeaf {
1808 WeightedLeaf(
SDValue Value,
int Weight,
int InsertionOrder) :
1809 Value(
Value), Weight(Weight), InsertionOrder(InsertionOrder) {
1810 assert(Weight >= 0 &&
"Weight must be >= 0");
1813 static bool Compare(
const WeightedLeaf &
A,
const WeightedLeaf &
B) {
1814 assert(
A.Value.getNode() &&
B.Value.getNode());
1815 return A.Weight ==
B.Weight ?
1816 (
A.InsertionOrder >
B.InsertionOrder) :
1817 (
A.Weight >
B.Weight);
1824class LeafPrioQueue {
1827 WeightedLeaf ConstElt;
1832 return (!HaveConst && Q.
empty());
1836 return Q.
size() + HaveConst;
1843 const WeightedLeaf &top() {
1849 WeightedLeaf pop() {
1854 std::pop_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1858 void push(WeightedLeaf L,
bool SeparateConst=
true) {
1859 if (!HaveConst && SeparateConst && isa<ConstantSDNode>(
L.Value)) {
1861 cast<ConstantSDNode>(
L.Value)->getSExtValue() == 1)
1864 cast<ConstantSDNode>(
L.Value)->getSExtValue() == 0)
1871 std::push_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1877 void pushToBottom(WeightedLeaf L) {
1884 WeightedLeaf findSHL(
uint64_t MaxAmount);
1886 WeightedLeaf findMULbyConst();
1888 LeafPrioQueue(
unsigned Opcode) :
1889 HaveConst(
false), Opcode(Opcode) { }
1893WeightedLeaf LeafPrioQueue::findSHL(
uint64_t MaxAmount) {
1897 for (
int Pos = 0,
End = Q.
size(); Pos !=
End; ++Pos) {
1898 const WeightedLeaf &
L = Q[Pos];
1905 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1912 if (
Result.Value.getNode()) {
1913 Q.
erase(&Q[ResultPos]);
1914 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1920WeightedLeaf LeafPrioQueue::findMULbyConst() {
1924 for (
int Pos = 0,
End = Q.
size(); Pos !=
End; ++Pos) {
1925 const WeightedLeaf &
L = Q[Pos];
1932 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1939 if (
Result.Value.getNode()) {
1940 Q.
erase(&Q[ResultPos]);
1941 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1948 uint64_t MulFactor = 1ull <<
N->getConstantOperandVal(1);
1950 N->getOperand(1).getValueType());
1956 unsigned MaxFactor = 0;
1957 for (
int i = 0; i < 2; ++i) {
1961 const APInt &CInt =
C->getAPIntValue();
1979 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
1980 for (
int i = 0; i < 2; ++i)
1981 if (isa<ConstantSDNode>(Ops[i].
getNode()) &&
1982 V.getConstantOperandVal(i) % (1ULL << Amount) == 0) {
1983 uint64_t NewConst = V.getConstantOperandVal(i) >> Amount;
1984 return (NewConst == 1);
1986 }
else if (V.getOpcode() ==
ISD::SHL) {
1987 return (Amount == V.getConstantOperandVal(1));
1993SDValue HexagonDAGToDAGISel::factorOutPowerOf2(
SDValue V,
unsigned Power) {
1994 SDValue Ops[] = {
V.getOperand(0),
V.getOperand(1) };
1996 for (
int i=0; i < 2; ++i) {
1997 if (isa<ConstantSDNode>(Ops[i].
getNode()) &&
1998 V.getConstantOperandVal(i) % ((
uint64_t)1 << Power) == 0) {
1999 uint64_t NewConst =
V.getConstantOperandVal(i) >> Power;
2003 SDLoc(V),
V.getValueType());
2008 uint64_t ShiftAmount =
V.getConstantOperandVal(1);
2009 if (ShiftAmount == Power)
2012 SDLoc(V),
V.getValueType());
2023unsigned HexagonDAGToDAGISel::getUsesInFunction(
const Value *V) {
2024 if (GAUsesInFunction.count(V))
2025 return GAUsesInFunction[
V];
2029 for (
const User *U :
V->users()) {
2030 if (isa<Instruction>(U) &&
2045SDValue HexagonDAGToDAGISel::balanceSubTree(
SDNode *
N,
bool TopLevel) {
2046 assert(RootWeights.count(
N) &&
"Cannot balance non-root node.");
2047 assert(RootWeights[
N] != -2 &&
"This node was RAUW'd!");
2051 if (RootWeights[
N] != -1)
2065 Weight = getWeight(balanceSubTree(Op0N).
getNode());
2068 Weight = getWeight(Op0N);
2070 SDNode *Op1N =
N->getOperand(1).getNode();
2072 Weight += getWeight(balanceSubTree(Op1N).
getNode());
2075 Weight += getWeight(Op1N);
2077 RootWeights[
N] = Weight;
2078 RootHeights[
N] = std::max(getHeight(
N->getOperand(0).getNode()),
2079 getHeight(
N->getOperand(1).getNode())) + 1;
2081 LLVM_DEBUG(
dbgs() <<
"--> No need to balance root (Weight=" << Weight
2082 <<
" Height=" << RootHeights[
N] <<
"): ");
2091 unsigned NOpcode =
N->getOpcode();
2093 LeafPrioQueue Leaves(NOpcode);
2101 bool CanFactorize =
false;
2102 WeightedLeaf Mul1, Mul2;
2103 unsigned MaxPowerOf2 = 0;
2108 bool HaveTopLevelShift =
false;
2114 HaveTopLevelShift =
true;
2118 int InsertionOrder = 0;
2120 bool Imbalanced =
false;
2121 int CurrentWeight = 0;
2122 while (!Worklist.
empty()) {
2128 int Weight = RootWeights[Child.
getNode()];
2130 Child = balanceSubTree(Child.
getNode());
2132 Weight = getWeight(Child.
getNode());
2133 }
else if (Weight == -2) {
2138 return balanceSubTree(
N, TopLevel);
2141 NodeHeights[Child] = 1;
2142 CurrentWeight += Weight;
2145 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&
2151 if (!Mul1.Value.getNode()) {
2152 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);
2153 MaxPowerOf2 = PowerOf2;
2155 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);
2156 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);
2159 if (MaxPowerOf2 > 3)
2162 CanFactorize =
true;
2165 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2168 int Weight = getWeight(Child.
getNode());
2170 NodeHeights[Child] = getHeight(Child.
getNode());
2171 CurrentWeight += Weight;
2174 GA = WeightedLeaf(Child, Weight, InsertionOrder++);
2176 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2180 unsigned ChildOpcode = Child.
getOpcode();
2181 assert(ChildOpcode == NOpcode ||
2187 Op1 = getMultiplierForSHL(Child.
getNode());
2192 assert(!NodeHeights.
count(Child) &&
"Parent visited before children?");
2199 if (std::abs(NodeHeights[Op1] - NodeHeights[Child->
getOperand(0)]) > 1)
2202 NodeHeights[Child] = std::max(NodeHeights[Op1],
2209 <<
" weight=" << CurrentWeight
2210 <<
" imbalanced=" << Imbalanced <<
"\n");
2216 LLVM_DEBUG(
dbgs() <<
"--> Found common factor for two MUL children!\n");
2217 int Weight = Mul1.Weight + Mul2.Weight;
2218 int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;
2219 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);
2220 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);
2222 Mul1Factored, Mul2Factored);
2224 Mul1.Value.getValueType());
2227 NodeHeights[
New] = Height;
2228 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));
2229 }
else if (Mul1.Value.getNode()) {
2233 if (Mul2.Value.getNode())
2235 CanFactorize =
false;
2241 bool CombinedGA =
false;
2242 if (NOpcode ==
ISD::ADD && GA.Value.getNode() && Leaves.hasConst() &&
2243 GA.Value.hasOneUse() &&
N->use_size() < 3) {
2245 cast<GlobalAddressSDNode>(GA.Value.getOperand(0));
2248 if (getUsesInFunction(GANode->
getGlobal()) == 1 &&
Offset->hasOneUse() &&
2251 <<
Offset->getSExtValue() <<
"): ");
2259 GA.Value.getValueType(), NewTGA);
2260 GA.Weight += Leaves.top().Weight;
2262 NodeHeights[GA.Value] = getHeight(GA.Value.getNode());
2271 RootWeights[
N] = CurrentWeight;
2272 RootHeights[
N] = NodeHeights[
SDValue(
N, 0)];
2278 if (NOpcode ==
ISD::ADD && GA.Value.getNode()) {
2279 WeightedLeaf
SHL = Leaves.findSHL(31);
2280 if (
SHL.Value.getNode()) {
2281 int Height = std::max(NodeHeights[GA.Value], NodeHeights[
SHL.Value]) + 1;
2283 GA.Value.getValueType(),
2284 GA.Value,
SHL.Value);
2285 GA.Weight =
SHL.Weight;
2286 NodeHeights[GA.Value] = Height;
2290 if (GA.Value.getNode())
2295 if (TopLevel && !CanFactorize && Leaves.hasConst()) {
2297 Leaves.pushToBottom(Leaves.pop());
2304 while (Leaves.size() > 1) {
2305 WeightedLeaf L0 = Leaves.pop();
2309 WeightedLeaf L1 = Leaves.findMULbyConst();
2310 if (!L1.Value.getNode())
2313 assert(L0.Weight <= L1.Weight &&
"Priority queue is broken!");
2316 int V0Weight = L0.Weight;
2318 int V1Weight = L1.Weight;
2321 if ((RootWeights.count(V0.
getNode()) && RootWeights[V0.
getNode()] == -2) ||
2322 (RootWeights.count(V1.
getNode()) && RootWeights[V1.
getNode()] == -2)) {
2324 return balanceSubTree(
N, TopLevel);
2329 EVT VT =
N->getValueType(0);
2339 "Children must have been visited before re-combining them!");
2340 int Height = std::max(NodeHeights[V0], NodeHeights[V1]) + 1;
2352 NodeHeights[NewNode] = Height;
2354 int Weight = V0Weight + V1Weight;
2355 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));
2358 <<
",Height=" << Height <<
"):\n");
2362 assert(Leaves.size() == 1);
2363 SDValue NewRoot = Leaves.top().Value;
2366 int Height = NodeHeights[NewRoot];
2389 RootWeights[
N] = -2;
2394 RootWeights[NewRoot.
getNode()] = Leaves.top().Weight;
2395 RootHeights[NewRoot.
getNode()] = Height;
2400void HexagonDAGToDAGISel::rebalanceAddressTrees() {
2411 if (RootWeights.count(
BasePtr.getNode()))
2414 LLVM_DEBUG(
dbgs() <<
"** Rebalancing address calculation in node: ");
2423 while (!Worklist.
empty()) {
2425 unsigned Opcode =
N->getOpcode();
2430 Worklist.
push_back(
N->getOperand(0).getNode());
2431 Worklist.
push_back(
N->getOperand(1).getNode());
2434 if (
N->hasOneUse() && Opcode ==
N->use_begin()->getOpcode())
2438 if (RootWeights.count(
N))
2441 RootWeights[
N] = -1;
2445 RootWeights[
BasePtr.getNode()] = -1;
2450 NewBasePtr,
N->getOperand(2));
2453 NewBasePtr,
N->getOperand(3));
2460 GAUsesInFunction.clear();
2461 RootHeights.clear();
2462 RootWeights.clear();
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
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")
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")
#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
HexagonDAGToDAGISelLegacy(HexagonTargetMachine &tm, CodeGenOptLevel OptLevel)
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.
Implement std::hash so that hash_code can be used in STL containers.
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.