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"
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);
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);
168 MVT::i32, MVT::Other,
Base,
174 if (LD->getValueType(0) == MVT::i64)
187 if (LD->getValueType(0) == MVT::i64)
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 };
217 CurDAG->getSignedTargetConstant(Inc->getSExtValue(), dl, MVT::i32);
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,
354 {IntN->getOperand(2), IntN->getOperand(3), IntN->getOperand(0)});
362 CurDAG->RemoveDeadNode(IntN);
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 };
415 CurDAG->RemoveDeadNode(IntN);
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 };
449 CurDAG->RemoveDeadNode(IntN);
475 SDValue Chain = ST->getChain();
481 EVT StoredVT = ST->getMemoryVT();
484 bool IsValidInc = HII->isValidAutoIncImm(StoredVT, Inc);
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) {
531 Value =
CurDAG->getTargetExtractSubreg(Hexagon::isub_lo,
532 dl, MVT::i32,
Value);
535 SDValue IncV =
CurDAG->getSignedTargetConstant(Inc, dl, MVT::i32);
562 CurDAG->RemoveDeadNode(ST);
584 auto Default = [
this,
N] () ->
void { SelectCode(
N); };
597 int32_t ValConst =
static_cast<int32_t
>(
598 static_cast<uint32_t>(
C->getSExtValue()) << ShlConst);
600 SDValue Val =
CurDAG->getTargetConstant(ValConst, dl, MVT::i32);
601 SDNode *Result =
CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
602 MVT::i32, Mul_0, Val);
620 static_cast<int32_t
>(1U << (ShlConst + C2->getSExtValue()));
623 CurDAG->getSignedTargetConstant(-ValConst, dl, MVT::i32);
624 SDNode *Result =
CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
625 MVT::i32, Shl2_0, Val);
653 unsigned IntNo =
N->getConstantOperandVal(1);
654 if (IntNo == Intrinsic::hexagon_V6_vgathermw ||
655 IntNo == Intrinsic::hexagon_V6_vgathermw_128B ||
656 IntNo == Intrinsic::hexagon_V6_vgathermh ||
657 IntNo == Intrinsic::hexagon_V6_vgathermh_128B ||
658 IntNo == Intrinsic::hexagon_V6_vgathermhw ||
659 IntNo == Intrinsic::hexagon_V6_vgathermhw_128B ||
660 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh ||
661 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh_128B) {
665 if (IntNo == Intrinsic::hexagon_V6_vgathermwq ||
666 IntNo == Intrinsic::hexagon_V6_vgathermwq_128B ||
667 IntNo == Intrinsic::hexagon_V6_vgathermhq ||
668 IntNo == Intrinsic::hexagon_V6_vgathermhq_128B ||
669 IntNo == Intrinsic::hexagon_V6_vgathermhwq ||
670 IntNo == Intrinsic::hexagon_V6_vgathermhwq_128B) {
691 case Intrinsic::hexagon_S2_vsplatrb:
694 case Intrinsic::hexagon_S2_vsplatrh:
697 case Intrinsic::hexagon_V6_vaddcarry:
698 case Intrinsic::hexagon_V6_vaddcarry_128B:
699 case Intrinsic::hexagon_V6_vsubcarry:
700 case Intrinsic::hexagon_V6_vsubcarry_128B:
711 if (keepsLowBits(V, Bits, U)) {
713 N->getOperand(0), U);
715 SelectCode(R.getNode());
723 MVT ResTy =
N->getValueType(0).getSimpleVT();
724 unsigned Idx =
N->getConstantOperandVal(1);
731 assert(Idx == 0 || Idx == ResLen);
733 unsigned SubReg = Idx == 0 ? Hexagon::isub_lo : Hexagon::isub_hi;
745 APInt A = CN->getValueAPF().bitcastToAPInt();
746 if (
N->getValueType(0) == MVT::f32) {
747 SDValue V =
CurDAG->getTargetConstant(
A.getZExtValue(), dl, MVT::i32);
751 if (
N->getValueType(0) == MVT::f64) {
752 SDValue V =
CurDAG->getTargetConstant(
A.getZExtValue(), dl, MVT::i64);
764 if (
N->getValueType(0) == MVT::i1) {
765 assert(!(
N->getAsZExtVal() >> 1));
793 R =
CurDAG->getMachineNode(Hexagon::PS_fi,
DL, MVT::i32, FI, Zero);
796 Register AR = HMFI.getStackAlignBaseReg();
799 R =
CurDAG->getMachineNode(Hexagon::PS_fia,
DL, MVT::i32,
Ops);
806 unsigned OpcCarry =
N->getOpcode() == HexagonISD::ADDC ? Hexagon::A4_addp_c
807 : Hexagon::A4_subp_c;
809 { N->getOperand(0), N->getOperand(1),
815 MVT ResTy =
N->getValueType(0).getSimpleVT();
816 if (HST->isHVXVectorType(ResTy,
true))
817 return SelectHvxVAlign(
N);
823 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
825 CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
827 CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
829 SDNode *R =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
836 if (HST->useCompound()) {
837 C =
CurDAG->getMachineNode(Hexagon::S4_andi_asl_ri, dl, MVT::i32,
838 M0,
N->getOperand(2),
M1);
840 SDNode *
T =
CurDAG->getMachineNode(Hexagon::S2_asl_i_r, dl, MVT::i32,
841 N->getOperand(2),
M1);
842 C =
CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
845 SDNode *S =
CurDAG->getMachineNode(Hexagon::S2_lsr_r_p, dl, MVT::i64,
847 SDValue E =
CurDAG->getTargetExtractSubreg(Hexagon::isub_lo, dl, ResTy,
852 SDNode *Pu =
CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::v8i1,
854 SDNode *VA =
CurDAG->getMachineNode(Hexagon::S2_valignrb, dl, ResTy,
855 N->getOperand(0),
N->getOperand(1),
868 SDNode *
AA =
CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
869 N->getOperand(0), M);
878 MVT OpTy =
Op.getValueType().getSimpleVT();
880 CurDAG->getVTList(OpTy), {Op});
885 MVT ResTy =
N->getValueType(0).getSimpleVT();
893 MVT ResTy =
N->getValueType(0).getSimpleVT();
895 SDNode *
T =
CurDAG->getMachineNode(Hexagon::A4_vcmpbgtui, dl, ResTy,
896 N->getOperand(0), Zero);
902 MVT ResTy =
N->getValueType(0).getSimpleVT();
904 MVT OpTy =
N->getOperand(0).getValueType().getSimpleVT(); (void)OpTy;
908 SDNode *R =
CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
C);
909 SDNode *
T =
CurDAG->getMachineNode(Hexagon::V6_vandvrt, dl, ResTy,
916 MVT ResTy =
N->getValueType(0).getSimpleVT();
921 SDNode *R =
CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
C);
922 SDNode *
T =
CurDAG->getMachineNode(Hexagon::V6_vandqrt, dl, ResTy,
931 Ops = {
N->getOperand(0),
N->getOperand(1)};
933 VTs =
CurDAG->getVTList(MVT::f32, MVT::f32);
934 SDNode *ResScale =
CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs,
Ops);
935 SDNode *
D =
CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32,
Ops);
939 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32,
C);
941 SDNode *n =
CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32,
Ops);
942 SDNode *Err =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
945 SDNode *NewRec =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
948 SDNode *newErr =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
952 Hexagon::A2_andir, dl, MVT::f32,
SDValue(n, 0),
953 CurDAG->getTargetConstant(0x80000000, dl, MVT::i32));
955 CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(q, 0),
958 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
961 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
SDValue(n, 0),
963 SDNode *NNewQ =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
968 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
SDValue(n, 0),
970 std::array<SDValue, 4> temp1 = {
SDValue(NNewQ, 0),
SDValue(NqErr, 0),
974 CurDAG->getMachineNode(Hexagon::F2_sffma_sc, dl, MVT::f32, OpValue1);
982 Ops = {
N->getOperand(0),
N->getOperand(1)};
984 VTs =
CurDAG->getVTList(MVT::f32, MVT::f32);
985 SDNode *ResScale =
CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs,
Ops);
986 SDNode *
D =
CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32,
Ops);
990 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32,
C);
992 SDNode *n =
CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32,
Ops);
993 SDNode *Err =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
996 SDNode *NewRec =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
999 SDNode *newErr =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
1004 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
1007 Hexagon::F2_sfmpy, dl, MVT::f32,
SDValue(NNewRec, 0),
SDValue(n, 0));
1012 if (
N->getFlags().hasAllowReassociation())
1019 if (
N->isMachineOpcode())
1020 return N->setNodeId(-1);
1022 auto isHvxOp = [
this](
SDNode *
N) {
1023 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
1024 if (HST->isHVXVectorType(
N->getValueType(i),
true))
1028 if (HST->isHVXVectorType(
I.getValueType(),
true))
1034 if (HST->useHVXOps() && isHvxOp(
N)) {
1035 switch (
N->getOpcode()) {
1043 switch (
N->getOpcode()) {
1054 case HexagonISD::ADDC:
1072 std::vector<SDValue> &OutOps) {
1075 switch (ConstraintID) {
1082 OutOps.push_back(Res);
1084 OutOps.push_back(Inp);
1088 OutOps.push_back(
CurDAG->getTargetConstant(0,
SDLoc(
Op), MVT::i32));
1097 if (!U->hasOneUse())
1099 unsigned Opc = U->getOpcode();
1122 SDNode *SYNode = SY.getNode();
1126 if (LDBasePtr == STBasePtr)
1135void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {
1136 SelectionDAG &DAG = *
CurDAG;
1138 for (
auto *
I : Nodes) {
1142 auto IsSelect0 = [](
const SDValue &
Op) ->
bool {
1149 SDValue N0 =
I->getOperand(0), N1 =
I->getOperand(1);
1150 EVT VT =
I->getValueType(0);
1151 bool SelN0 = IsSelect0(N0);
1152 SDValue SOp = SelN0 ? N0 : N1;
1153 SDValue VOp = SelN0 ? N1 : N0;
1179void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {
1180 SelectionDAG &DAG = *
CurDAG;
1182 for (
auto *
I : Nodes) {
1214 if (EV % (1 << CV) != 0)
1216 unsigned DV = EV / (1 << CV);
1219 SDLoc
DL = SDLoc(
I);
1243void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {
1244 SelectionDAG &DAG = *
CurDAG;
1246 for (SDNode *
N : Nodes) {
1247 unsigned Opc =
N->getOpcode();
1284 if (TZ +
M1 + LZ != 32)
1308void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {
1309 SelectionDAG &DAG = *
CurDAG;
1311 for (SDNode *
N : Nodes) {
1312 unsigned Opc =
N->getOpcode();
1319 for (SDUse &Use :
N->uses()) {
1320 SDNode *
U =
Use.getUser();
1321 if (
U->getNumValues() != 1)
1323 EVT UVT =
U->getValueType(0);
1333 unsigned I1N =
Use.getOperandNo();
1335 for (
unsigned i = 0, n =
U->getNumOperands(); i != n; ++i)
1336 Ops[i] =
U->getOperand(i);
1337 EVT BVT =
Ops[I1N].getValueType();
1345 unsigned UseOpc =
U->getMachineOpcode();
1351 unsigned UseOpc =
U->getOpcode();
1373 auto getNodes = [
this]() -> std::vector<SDNode *> {
1374 std::vector<SDNode *>
T;
1375 T.reserve(
CurDAG->allnodes_size());
1381 if (HST->useHVXOps())
1382 PreprocessHvxISelDAG();
1386 ppSimplifyOrSelect0(getNodes());
1394 ppAddrReorderAddShl(getNodes());
1409 ppAddrRewriteAndSrl(getNodes());
1413 ppHoistZextI1(getNodes());
1416 dbgs() <<
"Preprocessed (Hexagon) selection DAG:";
1421 rebalanceAddressTrees();
1424 dbgs() <<
"Address tree balanced selection DAG:";
1433 if (!HFI.needsAligna(*
MF))
1442 auto &HRI = *HST.getRegisterInfo();
1444 for (
const MCPhysReg *R = HRI.getCalleeSavedRegs(
MF); *R; ++R) {
1450 assert(AP.
isValid() &&
"Couldn't reserve stack align register");
1456void HexagonDAGToDAGISel::updateAligna() {
1458 if (!HFI.needsAligna(*
MF))
1460 auto *AlignaI =
const_cast<MachineInstr*
>(HFI.getAlignaInstr(*
MF));
1461 assert(AlignaI !=
nullptr);
1463 if (AlignaI->getOperand(1).getImm() < MaxA)
1464 AlignaI->getOperand(1).setImm(MaxA);
1471 auto &HFI = *HST->getFrameLowering();
1476 R =
CurDAG->getTargetFrameIndex(FX, MVT::i32);
1506 EVT T =
N.getValueType();
1510 R =
CurDAG->getTargetConstant(V,
SDLoc(
N),
N.getValueType());
1516 switch (
N.getOpcode()) {
1518 if (
N.getValueType() != MVT::i32)
1523 R =
CurDAG->getTargetConstant(V,
SDLoc(
N),
N.getValueType());
1526 case HexagonISD::JT:
1527 case HexagonISD::CP:
1529 if (Alignment >
Align(8))
1531 R =
N.getOperand(0);
1535 if (Alignment >
Align(1))
1541 if (Alignment >
Align(4) ||
1556 bool UseGP,
Align Alignment) {
1557 switch (
N.getOpcode()) {
1562 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1564 if (!UseGP && GAOpc != HexagonISD::CONST32)
1567 if (!
isAligned(Alignment, Const->getZExtValue()))
1573 R =
CurDAG->getTargetGlobalAddress(GA->getGlobal(),
SDLoc(Const),
1574 N.getValueType(), NewOff);
1581 case HexagonISD::CP:
1582 case HexagonISD::JT:
1583 case HexagonISD::CONST32:
1587 R =
N.getOperand(0);
1589 case HexagonISD::CONST32_GP:
1591 R =
N.getOperand(0);
1619 if (
N.getValueType() != MVT::i64)
1621 unsigned Opc =
N.getOpcode();
1627 ?
N.getOperand(0).getValueType()
1629 unsigned SW =
T.getSizeInBits();
1631 R =
N.getOperand(0);
1644 if (L->getMemoryVT().getSizeInBits() > 32)
1651 if (!S || S->getZExtValue() != 32)
1658 if (
T.getSizeInBits() == 32)
1659 R =
N.getOperand(0);
1668 EVT RT = R.getValueType();
1676 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
1677 R,
CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
1678 R,
CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
1680 SDNode *
T =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
1686bool HexagonDAGToDAGISel::keepsLowBits(
const SDValue &Val,
unsigned NumBits,
1695 if (
T.isInteger() &&
T.getSizeInBits() == NumBits) {
1706 if (
T->getVT().getSizeInBits() == NumBits) {
1714 uint64_t
Mask = (1ULL << NumBits) - 1;
1716 if (
C->getZExtValue() == Mask) {
1722 if (
C->getZExtValue() == Mask) {
1732 uint64_t
Mask = (1ULL << NumBits) - 1;
1734 if ((
C->getZExtValue() & Mask) == 0) {
1740 if ((
C->getZExtValue() & Mask) == 0) {
1753bool HexagonDAGToDAGISel::isAlignedMemNode(
const MemSDNode *
N)
const {
1754 return N->getAlign().value() >=
N->getMemoryVT().getStoreSize();
1757bool HexagonDAGToDAGISel::isSmallStackStore(
const StoreSDNode *
N)
const {
1758 unsigned StackSize =
MF->getFrameInfo().estimateStackSize(*
MF);
1759 switch (
N->getMemoryVT().getStoreSize()) {
1761 return StackSize <= 56;
1763 return StackSize <= 120;
1765 return StackSize <= 248;
1772bool HexagonDAGToDAGISel::isPositiveHalfWord(
const SDNode *
N)
const {
1784bool HexagonDAGToDAGISel::hasOneUse(
const SDNode *
N)
const {
1792 switch (
N->getOpcode()) {
1799 return N->getNumOperands() >= 2 &&
1807int HexagonDAGToDAGISel::getWeight(
SDNode *
N) {
1810 assert(RootWeights.count(
N) &&
"Cannot get weight of unseen root!");
1811 assert(RootWeights[
N] != -1 &&
"Cannot get weight of unvisited root!");
1812 assert(RootWeights[
N] != -2 &&
"Cannot get weight of RAWU'd root!");
1813 return RootWeights[
N];
1816int HexagonDAGToDAGISel::getHeight(
SDNode *
N) {
1819 assert(RootWeights.count(
N) && RootWeights[
N] >= 0 &&
1820 "Cannot query height of unvisited/RAUW'd node!");
1821 return RootHeights[
N];
1825struct WeightedLeaf {
1830 WeightedLeaf() =
default;
1832 WeightedLeaf(
SDValue Value,
int Weight,
int InsertionOrder) :
1833 Value(
Value), Weight(Weight), InsertionOrder(InsertionOrder) {
1834 assert(Weight >= 0 &&
"Weight must be >= 0");
1837 static bool Compare(
const WeightedLeaf &
A,
const WeightedLeaf &
B) {
1838 assert(
A.Value.getNode() &&
B.Value.getNode());
1839 return A.Weight ==
B.Weight ?
1840 (
A.InsertionOrder >
B.InsertionOrder) :
1841 (
A.Weight >
B.Weight);
1848class LeafPrioQueue {
1851 WeightedLeaf ConstElt;
1856 return (!HaveConst && Q.
empty());
1860 return Q.
size() + HaveConst;
1867 const WeightedLeaf &top() {
1873 WeightedLeaf pop() {
1878 std::pop_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1882 void push(WeightedLeaf L,
bool SeparateConst=
true) {
1895 std::push_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1901 void pushToBottom(WeightedLeaf L) {
1908 WeightedLeaf findSHL(uint64_t MaxAmount);
1910 WeightedLeaf findMULbyConst();
1912 LeafPrioQueue(
unsigned Opcode) :
1913 HaveConst(
false), Opcode(Opcode) { }
1917WeightedLeaf LeafPrioQueue::findSHL(uint64_t MaxAmount) {
1921 for (
int Pos = 0, End = Q.
size(); Pos != End; ++Pos) {
1922 const WeightedLeaf &
L = Q[Pos];
1929 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1936 if (
Result.Value.getNode()) {
1937 Q.
erase(&Q[ResultPos]);
1938 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1944WeightedLeaf LeafPrioQueue::findMULbyConst() {
1948 for (
int Pos = 0, End = Q.
size(); Pos != End; ++Pos) {
1949 const WeightedLeaf &
L = Q[Pos];
1956 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1963 if (
Result.Value.getNode()) {
1964 Q.
erase(&Q[ResultPos]);
1965 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1972 if (
N->getNumOperands() < 2)
1974 uint64_t MulFactor = 1ull <<
N->getConstantOperandVal(1);
1975 return CurDAG->getConstant(MulFactor, SDLoc(
N),
1976 N->getOperand(1).getValueType());
1984 unsigned MaxFactor = 0;
1985 for (
int i = 0; i < 2; ++i) {
1989 const APInt &CInt =
C->getAPIntValue();
2008 if (V.getNumOperands() < 2)
2010 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
2011 for (
int i = 0; i < 2; ++i)
2013 V.getConstantOperandVal(i) % (1ULL << Amount) == 0) {
2014 uint64_t NewConst = V.getConstantOperandVal(i) >> Amount;
2015 return (NewConst == 1);
2017 }
else if (V.getOpcode() ==
ISD::SHL) {
2018 if (V.getNumOperands() < 2 ||
2021 return (Amount == V.getConstantOperandVal(1));
2027SDValue HexagonDAGToDAGISel::factorOutPowerOf2(
SDValue V,
unsigned Power) {
2029 if (
V.getNumOperands() < 2)
2034 for (
int i=0; i < 2; ++i) {
2036 V.getConstantOperandVal(i) % ((uint64_t)1 << Power) == 0) {
2037 uint64_t NewConst =
V.getConstantOperandVal(i) >> Power;
2041 SDLoc(V),
V.getValueType());
2048 uint64_t ShiftAmount =
V.getConstantOperandVal(1);
2049 if (ShiftAmount == Power)
2051 Ops[1] =
CurDAG->getConstant(ShiftAmount - Power,
2052 SDLoc(V),
V.getValueType());
2055 return CurDAG->getNode(
V.getOpcode(), SDLoc(V),
V.getValueType(),
Ops);
2059 return V.getOpcode() == HexagonISD::CONST32 ||
2060 V.getOpcode() == HexagonISD::CONST32_GP;
2063unsigned HexagonDAGToDAGISel::getUsesInFunction(
const Value *V) {
2064 auto [It,
Inserted] = GAUsesInFunction.try_emplace(V);
2069 const Function &CurF =
CurDAG->getMachineFunction().getFunction();
2070 for (
const User *U :
V->users()) {
2086SDValue HexagonDAGToDAGISel::balanceSubTree(
SDNode *
N,
bool TopLevel) {
2087 assert(RootWeights.count(
N) &&
"Cannot balance non-root node.");
2088 assert(RootWeights[
N] != -2 &&
"This node was RAUW'd!");
2092 if (RootWeights[
N] != -1)
2097 if (
N->getNumOperands() < 2)
2109 Weight = getWeight(balanceSubTree(Op0N).
getNode());
2112 Weight = getWeight(Op0N);
2116 Weight += getWeight(balanceSubTree(Op1N).
getNode());
2119 Weight += getWeight(Op1N);
2121 RootWeights[
N] = Weight;
2125 int Height0 = 0, Height1 = 0;
2127 RootWeights[Op0N] >= 0)
2128 Height0 = getHeight(Op0N);
2130 RootWeights[Op1N] >= 0)
2131 Height1 = getHeight(Op1N);
2133 RootHeights[
N] = std::max(Height0, Height1) + 1;
2135 LLVM_DEBUG(
dbgs() <<
"--> No need to balance root (Weight=" << Weight
2136 <<
" Height=" << RootHeights[
N] <<
"): ");
2145 unsigned NOpcode =
N->getOpcode();
2147 LeafPrioQueue Leaves(NOpcode);
2155 bool CanFactorize =
false;
2156 WeightedLeaf Mul1, Mul2;
2157 unsigned MaxPowerOf2 = 0;
2162 bool HaveTopLevelShift =
false;
2168 HaveTopLevelShift =
true;
2172 int InsertionOrder = 0;
2173 SmallDenseMap<SDValue, int> NodeHeights;
2174 bool Imbalanced =
false;
2175 int CurrentWeight = 0;
2176 while (!Worklist.
empty()) {
2182 int Weight = RootWeights[Child.
getNode()];
2184 Child = balanceSubTree(Child.
getNode());
2186 Weight = getWeight(Child.
getNode());
2187 }
else if (Weight == -2) {
2192 return balanceSubTree(
N, TopLevel);
2195 NodeHeights[Child] = 1;
2196 CurrentWeight += Weight;
2199 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&
2206 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);
2207 MaxPowerOf2 = PowerOf2;
2209 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);
2210 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);
2213 if (MaxPowerOf2 > 3)
2216 CanFactorize =
true;
2219 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2222 int Weight = getWeight(Child.
getNode());
2224 NodeHeights[Child] = getHeight(Child.
getNode());
2225 CurrentWeight += Weight;
2228 GA = WeightedLeaf(Child, Weight, InsertionOrder++);
2230 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2234 unsigned ChildOpcode = Child.
getOpcode();
2235 assert(ChildOpcode == NOpcode ||
2240 int Weight = getWeight(Child.
getNode());
2241 NodeHeights[Child] = getHeight(Child.
getNode());
2242 CurrentWeight += Weight;
2243 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2250 Op1 = getMultiplierForSHL(Child.
getNode());
2251 assert(Op1.
getNode() &&
"getMultiplierForSHL returned null");
2256 assert(!NodeHeights.
count(Child) &&
"Parent visited before children?");
2263 if (std::abs(NodeHeights[Op1] - NodeHeights[Child->
getOperand(0)]) > 1)
2266 NodeHeights[Child] = std::max(NodeHeights[Op1],
2273 <<
" weight=" << CurrentWeight
2274 <<
" imbalanced=" << Imbalanced <<
"\n");
2280 LLVM_DEBUG(
dbgs() <<
"--> Found common factor for two MUL children!\n");
2281 int Weight = Mul1.Weight + Mul2.Weight;
2282 int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;
2283 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);
2284 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);
2286 Mul1Factored, Mul2Factored);
2291 NodeHeights[
New] = Height;
2292 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));
2293 }
else if (Mul1.Value.
getNode()) {
2299 CanFactorize =
false;
2305 bool CombinedGA =
false;
2309 GlobalAddressSDNode *GANode =
2313 if (getUsesInFunction(GANode->
getGlobal()) == 1 &&
Offset->hasOneUse() &&
2316 <<
Offset->getSExtValue() <<
"): ");
2325 GA.Weight += Leaves.top().Weight;
2327 NodeHeights[GA.Value] = getHeight(GA.Value.
getNode());
2336 RootWeights[
N] = CurrentWeight;
2337 RootHeights[
N] = NodeHeights[
SDValue(
N, 0)];
2344 WeightedLeaf
SHL = Leaves.findSHL(31);
2345 if (
SHL.Value.getNode()) {
2346 int Height = std::max(NodeHeights[GA.Value], NodeHeights[
SHL.Value]) + 1;
2349 GA.Value,
SHL.Value);
2350 GA.Weight =
SHL.Weight;
2351 NodeHeights[GA.Value] = Height;
2360 if (TopLevel && !CanFactorize && Leaves.hasConst()) {
2362 Leaves.pushToBottom(Leaves.pop());
2365 const DataLayout &
DL =
CurDAG->getDataLayout();
2369 while (Leaves.size() > 1) {
2370 WeightedLeaf L0 = Leaves.pop();
2374 WeightedLeaf L1 = Leaves.findMULbyConst();
2378 assert(L0.Weight <= L1.Weight &&
"Priority queue is broken!");
2381 int V0Weight = L0.Weight;
2383 int V1Weight = L1.Weight;
2386 if ((RootWeights.count(V0.
getNode()) && RootWeights[V0.
getNode()] == -2) ||
2387 (RootWeights.count(V1.
getNode()) && RootWeights[V1.
getNode()] == -2)) {
2389 return balanceSubTree(
N, TopLevel);
2394 EVT VT =
N->getValueType(0);
2404 "Children must have been visited before re-combining them!");
2405 int Height = std::max(NodeHeights[V0], NodeHeights[V1]) + 1;
2409 NewNode =
CurDAG->getNode(
2415 NewNode =
CurDAG->getNode(NOpcode, SDLoc(
N), VT, V0, V1);
2417 NodeHeights[NewNode] = Height;
2419 int Weight = V0Weight + V1Weight;
2420 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));
2423 <<
",Height=" << Height <<
"):\n");
2427 assert(Leaves.size() == 1);
2428 SDValue NewRoot = Leaves.top().Value;
2431 int Height = NodeHeights[NewRoot];
2439 NewRoot =
CurDAG->getNode(
2454 RootWeights[
N] = -2;
2459 RootWeights[NewRoot.
getNode()] = Leaves.top().Weight;
2460 RootHeights[NewRoot.
getNode()] = Height;
2465void HexagonDAGToDAGISel::rebalanceAddressTrees() {
2476 if (RootWeights.count(
BasePtr.getNode()))
2479 LLVM_DEBUG(
dbgs() <<
"** Rebalancing address calculation in node: ");
2485 if (
BasePtr->getNumOperands() < 2)
2491 while (!Worklist.
empty()) {
2493 unsigned Opcode =
N->getOpcode();
2498 if (
N->getNumOperands() < 2)
2501 Worklist.
push_back(
N->getOperand(0).getNode());
2502 Worklist.
push_back(
N->getOperand(1).getNode());
2505 if (
N->hasOneUse() && Opcode ==
N->user_begin()->getOpcode())
2509 RootWeights.try_emplace(
N, -1);
2513 RootWeights[
BasePtr.getNode()] = -1;
2517 if (
N->getNumOperands() >= 3)
2518 N =
CurDAG->UpdateNodeOperands(
N,
N->getOperand(0), NewBasePtr,
2521 if (
N->getNumOperands() >= 4)
2522 N =
CurDAG->UpdateNodeOperands(
N,
N->getOperand(0),
N->getOperand(1),
2523 NewBasePtr,
N->getOperand(3));
2530 CurDAG->RemoveDeadNodes();
2531 GAUsesInFunction.clear();
2532 RootHeights.clear();
2533 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
Function Alias Analysis false
static const Function * getParent(const Value *V)
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< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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"))
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#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.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
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.
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
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)
bool isIEEEHVXIntrinsic(unsigned)
void SelectAddSubCarry(SDNode *N)
void translateIEEEIntrinsicToQFloat(SDNode *N, unsigned &Opcode)
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)
HexagonDAGToDAGISel()=delete
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)
Hexagon target-specific information for each MachineFunction.
const HexagonFrameLowering * getFrameLowering() const override
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...
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.
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.
user_iterator user_begin() const
Provide iteration support to walk over all users of an 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
unsigned getNumOperands() const
SelectionDAGISelLegacy(char &ID, std::unique_ptr< SelectionDAGISel > S)
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
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 SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
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.
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
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...
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
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)
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
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.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
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)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
@ Default
The result value is 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.
constexpr 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 isVectorOf(EVT EltVT) const
Return true if this is a vector with matching element type.
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.