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->getSignedTargetConstant(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));
219 { IntN->getOperand(2), I, IntN->getOperand(4),
220 IntN->getOperand(0) });
235 unsigned Size = 1U << (SizeBits-1);
293 switch (
C->getConstantOperandVal(1)) {
294 case Intrinsic::hexagon_circ_ldub:
295 case Intrinsic::hexagon_circ_lduh:
298 case Intrinsic::hexagon_circ_ldw:
299 case Intrinsic::hexagon_circ_ldd:
306 if (
N->getExtensionType() != IntExt)
311 if (
C->getNumOperands() < 4 || Loc.
getNode() !=
C->getOperand(3).getNode())
333 const SDLoc &dl(IntN);
336 static const std::map<unsigned, unsigned> LoadBrevMap = {
337 { Intrinsic::hexagon_L2_loadrb_pbr, Hexagon::L2_loadrb_pbr },
338 { Intrinsic::hexagon_L2_loadrub_pbr, Hexagon::L2_loadrub_pbr },
339 { Intrinsic::hexagon_L2_loadrh_pbr, Hexagon::L2_loadrh_pbr },
340 { Intrinsic::hexagon_L2_loadruh_pbr, Hexagon::L2_loadruh_pbr },
341 { Intrinsic::hexagon_L2_loadri_pbr, Hexagon::L2_loadri_pbr },
342 { Intrinsic::hexagon_L2_loadrd_pbr, Hexagon::L2_loadrd_pbr }
344 auto FLI = LoadBrevMap.find(IntNo);
345 if (FLI != LoadBrevMap.end()) {
347 (IntNo == Intrinsic::hexagon_L2_loadrd_pbr) ? MVT::i64 : MVT::i32;
348 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
353 FLI->second, dl, RTys,
378 static std::map<unsigned,unsigned> LoadNPcMap = {
379 { Intrinsic::hexagon_L2_loadrub_pci, Hexagon::PS_loadrub_pci },
380 { Intrinsic::hexagon_L2_loadrb_pci, Hexagon::PS_loadrb_pci },
381 { Intrinsic::hexagon_L2_loadruh_pci, Hexagon::PS_loadruh_pci },
382 { Intrinsic::hexagon_L2_loadrh_pci, Hexagon::PS_loadrh_pci },
383 { Intrinsic::hexagon_L2_loadri_pci, Hexagon::PS_loadri_pci },
384 { Intrinsic::hexagon_L2_loadrd_pci, Hexagon::PS_loadrd_pci },
385 { Intrinsic::hexagon_L2_loadrub_pcr, Hexagon::PS_loadrub_pcr },
386 { Intrinsic::hexagon_L2_loadrb_pcr, Hexagon::PS_loadrb_pcr },
387 { Intrinsic::hexagon_L2_loadruh_pcr, Hexagon::PS_loadruh_pcr },
388 { Intrinsic::hexagon_L2_loadrh_pcr, Hexagon::PS_loadrh_pcr },
389 { Intrinsic::hexagon_L2_loadri_pcr, Hexagon::PS_loadri_pcr },
390 { Intrinsic::hexagon_L2_loadrd_pcr, Hexagon::PS_loadrd_pcr }
392 auto FLI = LoadNPcMap.find (IntNo);
393 if (FLI != LoadNPcMap.end()) {
394 EVT ValTy = MVT::i32;
395 if (IntNo == Intrinsic::hexagon_L2_loadrd_pci ||
396 IntNo == Intrinsic::hexagon_L2_loadrd_pcr)
398 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
401 auto Inc = cast<ConstantSDNode>(IntN->
getOperand(3));
419 static std::map<unsigned,unsigned> StoreNPcMap = {
420 { Intrinsic::hexagon_S2_storerb_pci, Hexagon::PS_storerb_pci },
421 { Intrinsic::hexagon_S2_storerh_pci, Hexagon::PS_storerh_pci },
422 { Intrinsic::hexagon_S2_storerf_pci, Hexagon::PS_storerf_pci },
423 { Intrinsic::hexagon_S2_storeri_pci, Hexagon::PS_storeri_pci },
424 { Intrinsic::hexagon_S2_storerd_pci, Hexagon::PS_storerd_pci },
425 { Intrinsic::hexagon_S2_storerb_pcr, Hexagon::PS_storerb_pcr },
426 { Intrinsic::hexagon_S2_storerh_pcr, Hexagon::PS_storerh_pcr },
427 { Intrinsic::hexagon_S2_storerf_pcr, Hexagon::PS_storerf_pcr },
428 { Intrinsic::hexagon_S2_storeri_pcr, Hexagon::PS_storeri_pcr },
429 { Intrinsic::hexagon_S2_storerd_pcr, Hexagon::PS_storerd_pcr }
431 auto FSI = StoreNPcMap.find (IntNo);
432 if (FSI != StoreNPcMap.end()) {
433 EVT RTys[] = { MVT::i32, MVT::Other };
436 auto Inc = cast<ConstantSDNode>(IntN->
getOperand(3));
475 SDValue Chain = ST->getChain();
480 int32_t Inc = cast<ConstantSDNode>(
Offset.getNode())->getSExtValue();
481 EVT StoredVT = ST->getMemoryVT();
490 Opcode = IsValidInc ? Hexagon::S2_storerb_pi : Hexagon::S2_storerb_io;
493 Opcode = IsValidInc ? Hexagon::S2_storerh_pi : Hexagon::S2_storerh_io;
499 Opcode = IsValidInc ? Hexagon::S2_storeri_pi : Hexagon::S2_storeri_io;
506 Opcode = IsValidInc ? Hexagon::S2_storerd_pi : Hexagon::S2_storerd_io;
516 if (isAlignedMemNode(ST)) {
517 if (ST->isNonTemporal())
518 Opcode = IsValidInc ? Hexagon::V6_vS32b_nt_pi : Hexagon::V6_vS32b_nt_ai;
520 Opcode = IsValidInc ? Hexagon::V6_vS32b_pi : Hexagon::V6_vS32b_ai;
522 Opcode = IsValidInc ? Hexagon::V6_vS32Ub_pi : Hexagon::V6_vS32Ub_ai;
529 if (ST->isTruncatingStore() && ValueVT.
getSizeInBits() == 64) {
532 dl, MVT::i32,
Value);
584 auto Default = [
this,
N] () ->
void { SelectCode(
N); };
590 int32_t ShlConst = cast<ConstantSDNode>(Shl_1)->getSExtValue();
597 int32_t ValConst =
C->getSExtValue() << ShlConst;
598 if (isInt<9>(ValConst)) {
601 MVT::i32, Mul_0, Val);
618 int32_t ValConst = 1 << (ShlConst + C2->getSExtValue());
619 if (isInt<9>(-ValConst)) {
623 MVT::i32, Shl2_0, Val);
651 unsigned IntNo =
N->getConstantOperandVal(1);
652 if (IntNo == Intrinsic::hexagon_V6_vgathermw ||
653 IntNo == Intrinsic::hexagon_V6_vgathermw_128B ||
654 IntNo == Intrinsic::hexagon_V6_vgathermh ||
655 IntNo == Intrinsic::hexagon_V6_vgathermh_128B ||
656 IntNo == Intrinsic::hexagon_V6_vgathermhw ||
657 IntNo == Intrinsic::hexagon_V6_vgathermhw_128B) {
661 if (IntNo == Intrinsic::hexagon_V6_vgathermwq ||
662 IntNo == Intrinsic::hexagon_V6_vgathermwq_128B ||
663 IntNo == Intrinsic::hexagon_V6_vgathermhq ||
664 IntNo == Intrinsic::hexagon_V6_vgathermhq_128B ||
665 IntNo == Intrinsic::hexagon_V6_vgathermhwq ||
666 IntNo == Intrinsic::hexagon_V6_vgathermhwq_128B) {
675 unsigned IID =
N->getConstantOperandVal(0);
678 case Intrinsic::hexagon_S2_vsplatrb:
681 case Intrinsic::hexagon_S2_vsplatrh:
684 case Intrinsic::hexagon_V6_vaddcarry:
685 case Intrinsic::hexagon_V6_vaddcarry_128B:
686 case Intrinsic::hexagon_V6_vsubcarry:
687 case Intrinsic::hexagon_V6_vsubcarry_128B:
698 if (keepsLowBits(V, Bits, U)) {
700 N->getOperand(0), U);
702 SelectCode(R.getNode());
710 MVT ResTy =
N->getValueType(0).getSimpleVT();
711 unsigned Idx =
N->getConstantOperandVal(1);
720 unsigned SubReg =
Idx == 0 ? Hexagon::isub_lo : Hexagon::isub_hi;
731 auto *CN = cast<ConstantFPSDNode>(
N);
732 APInt A = CN->getValueAPF().bitcastToAPInt();
733 if (
N->getValueType(0) == MVT::f32) {
738 if (
N->getValueType(0) == MVT::f64) {
751 if (
N->getValueType(0) == MVT::i1) {
752 assert(!(
N->getAsZExtVal() >> 1));
753 unsigned Opc = (cast<ConstantSDNode>(
N)->getSExtValue() != 0)
766 int FX = cast<FrameIndexSDNode>(
N)->getIndex();
783 Register AR = HMFI.getStackAlignBaseReg();
794 : Hexagon::A4_subp_c;
796 { N->getOperand(0), N->getOperand(1),
802 MVT ResTy =
N->getValueType(0).getSimpleVT();
804 return SelectHvxVAlign(
N);
825 M0,
N->getOperand(2),
M1);
828 N->getOperand(2),
M1);
842 N->getOperand(0),
N->getOperand(1),
851 int Mask = -cast<ConstantSDNode>(
A.getNode())->getSExtValue();
856 N->getOperand(0), M);
865 MVT OpTy =
Op.getValueType().getSimpleVT();
872 MVT ResTy =
N->getValueType(0).getSimpleVT();
880 MVT ResTy =
N->getValueType(0).getSimpleVT();
883 N->getOperand(0), Zero);
889 MVT ResTy =
N->getValueType(0).getSimpleVT();
891 MVT OpTy =
N->getOperand(0).getValueType().getSimpleVT(); (void)OpTy;
903 MVT ResTy =
N->getValueType(0).getSimpleVT();
918 Ops = {
N->getOperand(0),
N->getOperand(1)};
939 Hexagon::A2_andir, dl, MVT::f32,
SDValue(n, 0),
945 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
957 std::array<SDValue, 4> temp1 = {
SDValue(NNewQ, 0),
SDValue(NqErr, 0),
969 Ops = {
N->getOperand(0),
N->getOperand(1)};
991 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
994 Hexagon::F2_sfmpy, dl, MVT::f32,
SDValue(NNewRec, 0),
SDValue(n, 0));
999 if (
N->getFlags().hasAllowReassociation())
1006 if (
N->isMachineOpcode())
1007 return N->setNodeId(-1);
1009 auto isHvxOp = [
this](
SDNode *
N) {
1010 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
1022 switch (
N->getOpcode()) {
1030 switch (
N->getOpcode()) {
1059 std::vector<SDValue> &OutOps) {
1062 switch (ConstraintID) {
1069 OutOps.push_back(Res);
1071 OutOps.push_back(Inp);
1084 if (!U->hasOneUse())
1086 unsigned Opc = U->getOpcode();
1097 SDValue S0 = U->getOperand(0);
1101 SDNode *UUse = *U->user_begin();
1109 SDNode *SYNode = SY.getNode();
1111 SDValue LDBasePtr = cast<MemSDNode>(SYNode)->getBasePtr();
1112 SDValue STBasePtr = cast<MemSDNode>(UUse)->getBasePtr();
1113 if (LDBasePtr == STBasePtr)
1122void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {
1125 for (
auto *
I : Nodes) {
1129 auto IsSelect0 = [](
const SDValue &
Op) ->
bool {
1136 SDValue N0 =
I->getOperand(0), N1 =
I->getOperand(1);
1137 EVT VT =
I->getValueType(0);
1138 bool SelN0 = IsSelect0(N0);
1139 SDValue SOp = SelN0 ? N0 : N1;
1140 SDValue VOp = SelN0 ? N1 : N0;
1166void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {
1169 for (
auto *
I : Nodes) {
1201 if (EV % (1 << CV) != 0)
1203 unsigned DV = EV / (1 << CV);
1230void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {
1234 unsigned Opc =
N->getOpcode();
1271 if (TZ +
M1 + LZ != 32)
1295void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {
1299 unsigned Opc =
N->getOpcode();
1308 if (
U->getNumValues() != 1)
1310 EVT UVT =
U->getValueType(0);
1322 for (
unsigned i = 0, n =
U->getNumOperands(); i != n; ++i)
1323 Ops[i] =
U->getOperand(i);
1324 EVT BVT = Ops[I1N].getValueType();
1331 if (isa<MachineSDNode>(U)) {
1332 unsigned UseOpc =
U->getMachineOpcode();
1338 unsigned UseOpc =
U->getOpcode();
1340 If0 = DAG.
getNode(UseOpc, dl, UVT, Ops);
1342 If1 = DAG.
getNode(UseOpc, dl, UVT, Ops);
1360 auto getNodes = [
this]() -> std::vector<SDNode *> {
1361 std::vector<SDNode *>
T;
1369 PreprocessHvxISelDAG();
1373 ppSimplifyOrSelect0(getNodes());
1381 ppAddrReorderAddShl(getNodes());
1396 ppAddrRewriteAndSrl(getNodes());
1400 ppHoistZextI1(getNodes());
1403 dbgs() <<
"Preprocessed (Hexagon) selection DAG:";
1408 rebalanceAddressTrees();
1411 dbgs() <<
"Address tree balanced selection DAG:";
1420 if (!HFI.needsAligna(*
MF))
1437 assert(AP.
isValid() &&
"Couldn't reserve stack align register");
1443void HexagonDAGToDAGISel::updateAligna() {
1445 if (!HFI.needsAligna(*
MF))
1447 auto *AlignaI =
const_cast<MachineInstr*
>(HFI.getAlignaInstr(*
MF));
1448 assert(AlignaI !=
nullptr);
1450 if (AlignaI->getOperand(1).getImm() < MaxA)
1451 AlignaI->getOperand(1).setImm(MaxA);
1460 int FX = cast<FrameIndexSDNode>(
N)->getIndex();
1493 EVT T =
N.getValueType();
1494 if (!
T.isInteger() ||
T.getSizeInBits() != 32 || !isa<ConstantSDNode>(
N))
1496 uint32_t V = cast<const ConstantSDNode>(
N)->getZExtValue();
1503 switch (
N.getOpcode()) {
1505 if (
N.getValueType() != MVT::i32)
1507 uint32_t V = cast<const ConstantSDNode>(
N)->getZExtValue();
1516 if (Alignment >
Align(8))
1518 R =
N.getOperand(0);
1522 if (Alignment >
Align(1))
1528 if (Alignment >
Align(4) ||
1543 bool UseGP,
Align Alignment) {
1544 switch (
N.getOpcode()) {
1554 if (!
isAligned(Alignment, Const->getZExtValue()))
1561 N.getValueType(), NewOff);
1574 R =
N.getOperand(0);
1578 R =
N.getOperand(0);
1606 if (
N.getValueType() != MVT::i64)
1608 unsigned Opc =
N.getOpcode();
1614 ?
N.getOperand(0).getValueType()
1615 : cast<VTSDNode>(
N.getOperand(1))->getVT();
1616 unsigned SW =
T.getSizeInBits();
1618 R =
N.getOperand(0);
1631 if (L->getMemoryVT().getSizeInBits() > 32)
1637 auto *S = dyn_cast<ConstantSDNode>(
N.getOperand(1));
1638 if (!S || S->getZExtValue() != 32)
1644 EVT T = cast<VTSDNode>(
N.getOperand(1))->getVT();
1645 if (
T.getSizeInBits() == 32)
1646 R =
N.getOperand(0);
1655 EVT RT = R.getValueType();
1673bool HexagonDAGToDAGISel::keepsLowBits(
const SDValue &Val,
unsigned NumBits,
1682 if (
T.isInteger() &&
T.getSizeInBits() == NumBits) {
1693 if (
T->getVT().getSizeInBits() == NumBits) {
1703 if (
C->getZExtValue() ==
Mask) {
1709 if (
C->getZExtValue() ==
Mask) {
1721 if ((
C->getZExtValue() &
Mask) == 0) {
1727 if ((
C->getZExtValue() &
Mask) == 0) {
1740bool HexagonDAGToDAGISel::isAlignedMemNode(
const MemSDNode *
N)
const {
1741 return N->getAlign().value() >=
N->getMemoryVT().getStoreSize();
1744bool HexagonDAGToDAGISel::isSmallStackStore(
const StoreSDNode *
N)
const {
1746 switch (
N->getMemoryVT().getStoreSize()) {
1748 return StackSize <= 56;
1750 return StackSize <= 120;
1752 return StackSize <= 248;
1759bool HexagonDAGToDAGISel::isPositiveHalfWord(
const SDNode *
N)
const {
1762 return V > 0 && isInt<16>(V);
1765 const VTSDNode *VN = dyn_cast<const VTSDNode>(
N->getOperand(1));
1771bool HexagonDAGToDAGISel::hasOneUse(
const SDNode *
N)
const {
1779 switch (
N->getOpcode()) {
1786 return isa<ConstantSDNode>(
N->getOperand(1).getNode());
1793int HexagonDAGToDAGISel::getWeight(
SDNode *
N) {
1796 assert(RootWeights.count(
N) &&
"Cannot get weight of unseen root!");
1797 assert(RootWeights[
N] != -1 &&
"Cannot get weight of unvisited root!");
1798 assert(RootWeights[
N] != -2 &&
"Cannot get weight of RAWU'd root!");
1799 return RootWeights[
N];
1802int HexagonDAGToDAGISel::getHeight(
SDNode *
N) {
1805 assert(RootWeights.count(
N) && RootWeights[
N] >= 0 &&
1806 "Cannot query height of unvisited/RAUW'd node!");
1807 return RootHeights[
N];
1811struct WeightedLeaf {
1818 WeightedLeaf(
SDValue Value,
int Weight,
int InsertionOrder) :
1819 Value(
Value), Weight(Weight), InsertionOrder(InsertionOrder) {
1820 assert(Weight >= 0 &&
"Weight must be >= 0");
1823 static bool Compare(
const WeightedLeaf &
A,
const WeightedLeaf &
B) {
1824 assert(
A.Value.getNode() &&
B.Value.getNode());
1825 return A.Weight ==
B.Weight ?
1826 (
A.InsertionOrder >
B.InsertionOrder) :
1827 (
A.Weight >
B.Weight);
1834class LeafPrioQueue {
1837 WeightedLeaf ConstElt;
1842 return (!HaveConst && Q.
empty());
1846 return Q.
size() + HaveConst;
1853 const WeightedLeaf &top() {
1859 WeightedLeaf pop() {
1864 std::pop_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1868 void push(WeightedLeaf L,
bool SeparateConst=
true) {
1869 if (!HaveConst && SeparateConst && isa<ConstantSDNode>(
L.Value)) {
1871 cast<ConstantSDNode>(
L.Value)->getSExtValue() == 1)
1874 cast<ConstantSDNode>(
L.Value)->getSExtValue() == 0)
1881 std::push_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1887 void pushToBottom(WeightedLeaf L) {
1894 WeightedLeaf findSHL(
uint64_t MaxAmount);
1896 WeightedLeaf findMULbyConst();
1898 LeafPrioQueue(
unsigned Opcode) :
1899 HaveConst(
false), Opcode(Opcode) { }
1903WeightedLeaf LeafPrioQueue::findSHL(
uint64_t MaxAmount) {
1907 for (
int Pos = 0,
End = Q.
size(); Pos !=
End; ++Pos) {
1908 const WeightedLeaf &
L = Q[Pos];
1915 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1922 if (
Result.Value.getNode()) {
1923 Q.
erase(&Q[ResultPos]);
1924 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1930WeightedLeaf LeafPrioQueue::findMULbyConst() {
1934 for (
int Pos = 0,
End = Q.
size(); Pos !=
End; ++Pos) {
1935 const WeightedLeaf &
L = Q[Pos];
1942 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1949 if (
Result.Value.getNode()) {
1950 Q.
erase(&Q[ResultPos]);
1951 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1958 uint64_t MulFactor = 1ull <<
N->getConstantOperandVal(1);
1960 N->getOperand(1).getValueType());
1966 unsigned MaxFactor = 0;
1967 for (
int i = 0; i < 2; ++i) {
1971 const APInt &CInt =
C->getAPIntValue();
1989 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
1990 for (
int i = 0; i < 2; ++i)
1991 if (isa<ConstantSDNode>(Ops[i].
getNode()) &&
1992 V.getConstantOperandVal(i) % (1ULL << Amount) == 0) {
1993 uint64_t NewConst = V.getConstantOperandVal(i) >> Amount;
1994 return (NewConst == 1);
1996 }
else if (V.getOpcode() ==
ISD::SHL) {
1997 return (Amount == V.getConstantOperandVal(1));
2003SDValue HexagonDAGToDAGISel::factorOutPowerOf2(
SDValue V,
unsigned Power) {
2004 SDValue Ops[] = {
V.getOperand(0),
V.getOperand(1) };
2006 for (
int i=0; i < 2; ++i) {
2007 if (isa<ConstantSDNode>(Ops[i].
getNode()) &&
2008 V.getConstantOperandVal(i) % ((
uint64_t)1 << Power) == 0) {
2009 uint64_t NewConst =
V.getConstantOperandVal(i) >> Power;
2013 SDLoc(V),
V.getValueType());
2018 uint64_t ShiftAmount =
V.getConstantOperandVal(1);
2019 if (ShiftAmount == Power)
2022 SDLoc(V),
V.getValueType());
2033unsigned HexagonDAGToDAGISel::getUsesInFunction(
const Value *V) {
2034 auto [It,
Inserted] = GAUsesInFunction.try_emplace(V);
2040 for (
const User *U :
V->users()) {
2041 if (isa<Instruction>(U) &&
2056SDValue HexagonDAGToDAGISel::balanceSubTree(
SDNode *
N,
bool TopLevel) {
2057 assert(RootWeights.count(
N) &&
"Cannot balance non-root node.");
2058 assert(RootWeights[
N] != -2 &&
"This node was RAUW'd!");
2062 if (RootWeights[
N] != -1)
2076 Weight = getWeight(balanceSubTree(Op0N).
getNode());
2079 Weight = getWeight(Op0N);
2081 SDNode *Op1N =
N->getOperand(1).getNode();
2083 Weight += getWeight(balanceSubTree(Op1N).
getNode());
2086 Weight += getWeight(Op1N);
2088 RootWeights[
N] = Weight;
2089 RootHeights[
N] = std::max(getHeight(
N->getOperand(0).getNode()),
2090 getHeight(
N->getOperand(1).getNode())) + 1;
2092 LLVM_DEBUG(
dbgs() <<
"--> No need to balance root (Weight=" << Weight
2093 <<
" Height=" << RootHeights[
N] <<
"): ");
2102 unsigned NOpcode =
N->getOpcode();
2104 LeafPrioQueue Leaves(NOpcode);
2112 bool CanFactorize =
false;
2113 WeightedLeaf Mul1, Mul2;
2114 unsigned MaxPowerOf2 = 0;
2119 bool HaveTopLevelShift =
false;
2125 HaveTopLevelShift =
true;
2129 int InsertionOrder = 0;
2131 bool Imbalanced =
false;
2132 int CurrentWeight = 0;
2133 while (!Worklist.
empty()) {
2139 int Weight = RootWeights[Child.
getNode()];
2141 Child = balanceSubTree(Child.
getNode());
2143 Weight = getWeight(Child.
getNode());
2144 }
else if (Weight == -2) {
2149 return balanceSubTree(
N, TopLevel);
2152 NodeHeights[Child] = 1;
2153 CurrentWeight += Weight;
2156 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&
2162 if (!Mul1.Value.getNode()) {
2163 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);
2164 MaxPowerOf2 = PowerOf2;
2166 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);
2167 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);
2170 if (MaxPowerOf2 > 3)
2173 CanFactorize =
true;
2176 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2179 int Weight = getWeight(Child.
getNode());
2181 NodeHeights[Child] = getHeight(Child.
getNode());
2182 CurrentWeight += Weight;
2185 GA = WeightedLeaf(Child, Weight, InsertionOrder++);
2187 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2191 unsigned ChildOpcode = Child.
getOpcode();
2192 assert(ChildOpcode == NOpcode ||
2198 Op1 = getMultiplierForSHL(Child.
getNode());
2203 assert(!NodeHeights.
count(Child) &&
"Parent visited before children?");
2210 if (std::abs(NodeHeights[Op1] - NodeHeights[Child->
getOperand(0)]) > 1)
2213 NodeHeights[Child] = std::max(NodeHeights[Op1],
2220 <<
" weight=" << CurrentWeight
2221 <<
" imbalanced=" << Imbalanced <<
"\n");
2227 LLVM_DEBUG(
dbgs() <<
"--> Found common factor for two MUL children!\n");
2228 int Weight = Mul1.Weight + Mul2.Weight;
2229 int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;
2230 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);
2231 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);
2233 Mul1Factored, Mul2Factored);
2235 Mul1.Value.getValueType());
2238 NodeHeights[
New] = Height;
2239 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));
2240 }
else if (Mul1.Value.getNode()) {
2244 if (Mul2.Value.getNode())
2246 CanFactorize =
false;
2252 bool CombinedGA =
false;
2253 if (NOpcode ==
ISD::ADD && GA.Value.getNode() && Leaves.hasConst() &&
2254 GA.Value.hasOneUse() &&
N->use_size() < 3) {
2256 cast<GlobalAddressSDNode>(GA.Value.getOperand(0));
2259 if (getUsesInFunction(GANode->
getGlobal()) == 1 &&
Offset->hasOneUse() &&
2262 <<
Offset->getSExtValue() <<
"): ");
2270 GA.Value.getValueType(), NewTGA);
2271 GA.Weight += Leaves.top().Weight;
2273 NodeHeights[GA.Value] = getHeight(GA.Value.getNode());
2282 RootWeights[
N] = CurrentWeight;
2283 RootHeights[
N] = NodeHeights[
SDValue(
N, 0)];
2289 if (NOpcode ==
ISD::ADD && GA.Value.getNode()) {
2290 WeightedLeaf
SHL = Leaves.findSHL(31);
2291 if (
SHL.Value.getNode()) {
2292 int Height = std::max(NodeHeights[GA.Value], NodeHeights[
SHL.Value]) + 1;
2294 GA.Value.getValueType(),
2295 GA.Value,
SHL.Value);
2296 GA.Weight =
SHL.Weight;
2297 NodeHeights[GA.Value] = Height;
2301 if (GA.Value.getNode())
2306 if (TopLevel && !CanFactorize && Leaves.hasConst()) {
2308 Leaves.pushToBottom(Leaves.pop());
2315 while (Leaves.size() > 1) {
2316 WeightedLeaf L0 = Leaves.pop();
2320 WeightedLeaf L1 = Leaves.findMULbyConst();
2321 if (!L1.Value.getNode())
2324 assert(L0.Weight <= L1.Weight &&
"Priority queue is broken!");
2327 int V0Weight = L0.Weight;
2329 int V1Weight = L1.Weight;
2332 if ((RootWeights.count(V0.
getNode()) && RootWeights[V0.
getNode()] == -2) ||
2333 (RootWeights.count(V1.
getNode()) && RootWeights[V1.
getNode()] == -2)) {
2335 return balanceSubTree(
N, TopLevel);
2340 EVT VT =
N->getValueType(0);
2350 "Children must have been visited before re-combining them!");
2351 int Height = std::max(NodeHeights[V0], NodeHeights[V1]) + 1;
2363 NodeHeights[NewNode] = Height;
2365 int Weight = V0Weight + V1Weight;
2366 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));
2369 <<
",Height=" << Height <<
"):\n");
2373 assert(Leaves.size() == 1);
2374 SDValue NewRoot = Leaves.top().Value;
2377 int Height = NodeHeights[NewRoot];
2400 RootWeights[
N] = -2;
2405 RootWeights[NewRoot.
getNode()] = Leaves.top().Weight;
2406 RootHeights[NewRoot.
getNode()] = Height;
2411void HexagonDAGToDAGISel::rebalanceAddressTrees() {
2422 if (RootWeights.count(
BasePtr.getNode()))
2425 LLVM_DEBUG(
dbgs() <<
"** Rebalancing address calculation in node: ");
2434 while (!Worklist.
empty()) {
2436 unsigned Opcode =
N->getOpcode();
2441 Worklist.
push_back(
N->getOperand(0).getNode());
2442 Worklist.
push_back(
N->getOperand(1).getNode());
2445 if (
N->hasOneUse() && Opcode ==
N->user_begin()->getOpcode())
2449 RootWeights.try_emplace(
N, -1);
2453 RootWeights[
BasePtr.getNode()] = -1;
2458 NewBasePtr,
N->getOperand(2));
2461 NewBasePtr,
N->getOperand(3));
2468 GAUsesInFunction.clear();
2469 RootHeights.clear();
2470 RootWeights.clear();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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
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)
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
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...
LLVM_ABI 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.
LLVM_ABI 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.
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.
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)
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI 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),...
LLVM_ABI 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.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
LLVM_ABI 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)
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI 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())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI 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.
LLVM_ABI void dump() const
LLVM_ABI void RemoveDeadNodes()
This method deletes all unreachable nodes in the SelectionDAG.
LLVM_ABI void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
LLVM_ABI 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()
LLVM_ABI 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
LLVM_ABI 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...
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
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).
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.
LLVM_ABI 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.
LLVM_ABI 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.