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);
369 unsigned MOp,
unsigned CSOp) {
373 const SDValue RegSequenceOps[] = {RC,
N->getOperand(MOp), SubRegM,
374 N->getOperand(CSOp), SubRegCS};
390 static std::map<unsigned,unsigned> LoadNPcMap = {
391 { Intrinsic::hexagon_L2_loadrub_pci, Hexagon::PS_loadrub_pci },
392 { Intrinsic::hexagon_L2_loadrb_pci, Hexagon::PS_loadrb_pci },
393 { Intrinsic::hexagon_L2_loadruh_pci, Hexagon::PS_loadruh_pci },
394 { Intrinsic::hexagon_L2_loadrh_pci, Hexagon::PS_loadrh_pci },
395 { Intrinsic::hexagon_L2_loadri_pci, Hexagon::PS_loadri_pci },
396 { Intrinsic::hexagon_L2_loadrd_pci, Hexagon::PS_loadrd_pci },
397 { Intrinsic::hexagon_L2_loadrub_pcr, Hexagon::PS_loadrub_pcr },
398 { Intrinsic::hexagon_L2_loadrb_pcr, Hexagon::PS_loadrb_pcr },
399 { Intrinsic::hexagon_L2_loadruh_pcr, Hexagon::PS_loadruh_pcr },
400 { Intrinsic::hexagon_L2_loadrh_pcr, Hexagon::PS_loadrh_pcr },
401 { Intrinsic::hexagon_L2_loadri_pcr, Hexagon::PS_loadri_pcr },
402 { Intrinsic::hexagon_L2_loadrd_pcr, Hexagon::PS_loadrd_pcr }
404 auto FLI = LoadNPcMap.find (IntNo);
405 if (FLI != LoadNPcMap.end()) {
406 EVT ValTy = MVT::i32;
407 if (IntNo == Intrinsic::hexagon_L2_loadrd_pci ||
408 IntNo == Intrinsic::hexagon_L2_loadrd_pcr)
410 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
428 CurDAG->RemoveDeadNode(IntN);
432 static std::map<unsigned,unsigned> StoreNPcMap = {
433 { Intrinsic::hexagon_S2_storerb_pci, Hexagon::PS_storerb_pci },
434 { Intrinsic::hexagon_S2_storerh_pci, Hexagon::PS_storerh_pci },
435 { Intrinsic::hexagon_S2_storerf_pci, Hexagon::PS_storerf_pci },
436 { Intrinsic::hexagon_S2_storeri_pci, Hexagon::PS_storeri_pci },
437 { Intrinsic::hexagon_S2_storerd_pci, Hexagon::PS_storerd_pci },
438 { Intrinsic::hexagon_S2_storerb_pcr, Hexagon::PS_storerb_pcr },
439 { Intrinsic::hexagon_S2_storerh_pcr, Hexagon::PS_storerh_pcr },
440 { Intrinsic::hexagon_S2_storerf_pcr, Hexagon::PS_storerf_pcr },
441 { Intrinsic::hexagon_S2_storeri_pcr, Hexagon::PS_storeri_pcr },
442 { Intrinsic::hexagon_S2_storerd_pcr, Hexagon::PS_storerd_pcr }
444 auto FSI = StoreNPcMap.find (IntNo);
445 if (FSI != StoreNPcMap.end()) {
446 EVT RTys[] = { MVT::i32, MVT::Other };
465 CurDAG->RemoveDeadNode(IntN);
491 SDValue Chain = ST->getChain();
497 EVT StoredVT = ST->getMemoryVT();
500 bool IsValidInc = HII->isValidAutoIncImm(StoredVT, Inc);
506 Opcode = IsValidInc ? Hexagon::S2_storerb_pi : Hexagon::S2_storerb_io;
509 Opcode = IsValidInc ? Hexagon::S2_storerh_pi : Hexagon::S2_storerh_io;
515 Opcode = IsValidInc ? Hexagon::S2_storeri_pi : Hexagon::S2_storeri_io;
522 Opcode = IsValidInc ? Hexagon::S2_storerd_pi : Hexagon::S2_storerd_io;
532 if (isAlignedMemNode(ST)) {
533 if (ST->isNonTemporal())
534 Opcode = IsValidInc ? Hexagon::V6_vS32b_nt_pi : Hexagon::V6_vS32b_nt_ai;
536 Opcode = IsValidInc ? Hexagon::V6_vS32b_pi : Hexagon::V6_vS32b_ai;
538 Opcode = IsValidInc ? Hexagon::V6_vS32Ub_pi : Hexagon::V6_vS32Ub_ai;
545 if (ST->isTruncatingStore() && ValueVT.
getSizeInBits() == 64) {
547 Value =
CurDAG->getTargetExtractSubreg(Hexagon::isub_lo,
548 dl, MVT::i32,
Value);
551 SDValue IncV =
CurDAG->getSignedTargetConstant(Inc, dl, MVT::i32);
578 CurDAG->RemoveDeadNode(ST);
600 auto Default = [
this,
N] () ->
void { SelectCode(
N); };
613 int32_t ValConst =
static_cast<int32_t
>(
614 static_cast<uint32_t>(
C->getSExtValue()) << ShlConst);
616 SDValue Val =
CurDAG->getTargetConstant(ValConst, dl, MVT::i32);
617 SDNode *Result =
CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
618 MVT::i32, Mul_0, Val);
636 static_cast<int32_t
>(1U << (ShlConst + C2->getSExtValue()));
639 CurDAG->getSignedTargetConstant(-ValConst, dl, MVT::i32);
640 SDNode *Result =
CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
641 MVT::i32, Shl2_0, Val);
669 unsigned IntNo =
N->getConstantOperandVal(1);
670 if (IntNo == Intrinsic::hexagon_V6_vgathermw ||
671 IntNo == Intrinsic::hexagon_V6_vgathermw_128B ||
672 IntNo == Intrinsic::hexagon_V6_vgathermh ||
673 IntNo == Intrinsic::hexagon_V6_vgathermh_128B ||
674 IntNo == Intrinsic::hexagon_V6_vgathermhw ||
675 IntNo == Intrinsic::hexagon_V6_vgathermhw_128B ||
676 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh ||
677 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh_128B) {
681 if (IntNo == Intrinsic::hexagon_V6_vgathermwq ||
682 IntNo == Intrinsic::hexagon_V6_vgathermwq_128B ||
683 IntNo == Intrinsic::hexagon_V6_vgathermhq ||
684 IntNo == Intrinsic::hexagon_V6_vgathermhq_128B ||
685 IntNo == Intrinsic::hexagon_V6_vgathermhwq ||
686 IntNo == Intrinsic::hexagon_V6_vgathermhwq_128B) {
707 case Intrinsic::hexagon_S2_vsplatrb:
710 case Intrinsic::hexagon_S2_vsplatrh:
713 case Intrinsic::hexagon_V6_vaddcarry:
714 case Intrinsic::hexagon_V6_vaddcarry_128B:
715 case Intrinsic::hexagon_V6_vsubcarry:
716 case Intrinsic::hexagon_V6_vsubcarry_128B:
727 if (keepsLowBits(V, Bits, U)) {
729 N->getOperand(0), U);
731 SelectCode(R.getNode());
739 MVT ResTy =
N->getValueType(0).getSimpleVT();
740 unsigned Idx =
N->getConstantOperandVal(1);
747 assert(Idx == 0 || Idx == ResLen);
749 unsigned SubReg = Idx == 0 ? Hexagon::isub_lo : Hexagon::isub_hi;
761 APInt A = CN->getValueAPF().bitcastToAPInt();
762 if (
N->getValueType(0) == MVT::f32) {
763 SDValue V =
CurDAG->getTargetConstant(
A.getZExtValue(), dl, MVT::i32);
767 if (
N->getValueType(0) == MVT::f64) {
768 SDValue V =
CurDAG->getTargetConstant(
A.getZExtValue(), dl, MVT::i64);
780 if (
N->getValueType(0) == MVT::i1) {
781 assert(!(
N->getAsZExtVal() >> 1));
809 R =
CurDAG->getMachineNode(Hexagon::PS_fi,
DL, MVT::i32, FI,
Zero);
812 Register AR = HMFI.getStackAlignBaseReg();
813 assert(AR.isValid() &&
"Missing stack align base register");
816 R =
CurDAG->getMachineNode(Hexagon::PS_fia,
DL, MVT::i32,
Ops);
823 unsigned OpcCarry =
N->getOpcode() == HexagonISD::ADDC ? Hexagon::A4_addp_c
824 : Hexagon::A4_subp_c;
826 { N->getOperand(0), N->getOperand(1),
832 MVT ResTy =
N->getValueType(0).getSimpleVT();
833 if (HST->isHVXVectorType(ResTy,
true))
834 return SelectHvxVAlign(
N);
840 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
842 CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
844 CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
846 SDNode *R =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
853 if (HST->useCompound()) {
854 C =
CurDAG->getMachineNode(Hexagon::S4_andi_asl_ri, dl, MVT::i32,
855 M0,
N->getOperand(2),
M1);
857 SDNode *
T =
CurDAG->getMachineNode(Hexagon::S2_asl_i_r, dl, MVT::i32,
858 N->getOperand(2),
M1);
859 C =
CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
862 SDNode *S =
CurDAG->getMachineNode(Hexagon::S2_lsr_r_p, dl, MVT::i64,
864 SDValue E =
CurDAG->getTargetExtractSubreg(Hexagon::isub_lo, dl, ResTy,
869 SDNode *Pu =
CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::v8i1,
871 SDNode *VA =
CurDAG->getMachineNode(Hexagon::S2_valignrb, dl, ResTy,
872 N->getOperand(0),
N->getOperand(1),
885 SDNode *
AA =
CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
886 N->getOperand(0), M);
895 MVT OpTy =
Op.getValueType().getSimpleVT();
902 MVT ResTy =
N->getValueType(0).getSimpleVT();
910 MVT ResTy =
N->getValueType(0).getSimpleVT();
912 SDNode *
T =
CurDAG->getMachineNode(Hexagon::A4_vcmpbgtui, dl, ResTy,
913 N->getOperand(0),
Zero);
919 MVT ResTy =
N->getValueType(0).getSimpleVT();
921 MVT OpTy =
N->getOperand(0).getValueType().getSimpleVT(); (void)
OpTy;
922 assert(HST->getVectorLength() * 8 ==
OpTy.getSizeInBits());
925 SDNode *R =
CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
C);
926 SDNode *
T =
CurDAG->getMachineNode(Hexagon::V6_vandvrt, dl, ResTy,
933 MVT ResTy =
N->getValueType(0).getSimpleVT();
938 SDNode *R =
CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
C);
939 SDNode *
T =
CurDAG->getMachineNode(Hexagon::V6_vandqrt, dl, ResTy,
948 Ops = {
N->getOperand(0),
N->getOperand(1)};
950 VTs =
CurDAG->getVTList(MVT::f32, MVT::f32);
951 SDNode *ResScale =
CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs,
Ops);
952 SDNode *
D =
CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32,
Ops);
956 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32,
C);
958 SDNode *n =
CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32,
Ops);
959 SDNode *Err =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
962 SDNode *NewRec =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
965 SDNode *newErr =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
969 Hexagon::A2_andir, dl, MVT::f32,
SDValue(n, 0),
970 CurDAG->getTargetConstant(0x80000000, dl, MVT::i32));
972 CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(q, 0),
975 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
978 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
SDValue(n, 0),
980 SDNode *NNewQ =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
985 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
SDValue(n, 0),
987 std::array<SDValue, 4> temp1 = {
SDValue(NNewQ, 0),
SDValue(NqErr, 0),
991 CurDAG->getMachineNode(Hexagon::F2_sffma_sc, dl, MVT::f32, OpValue1);
999 Ops = {
N->getOperand(0),
N->getOperand(1)};
1001 VTs =
CurDAG->getVTList(MVT::f32, MVT::f32);
1002 SDNode *ResScale =
CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs,
Ops);
1003 SDNode *
D =
CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32,
Ops);
1007 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32,
C);
1009 SDNode *n =
CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32,
Ops);
1010 SDNode *Err =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
1013 SDNode *NewRec =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
1016 SDNode *newErr =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
1021 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
1024 Hexagon::F2_sfmpy, dl, MVT::f32,
SDValue(NNewRec, 0),
SDValue(n, 0));
1029 if (
N->getFlags().hasAllowReassociation())
1036 if (
N->isMachineOpcode())
1037 return N->setNodeId(-1);
1039 auto isHvxOp = [
this](
SDNode *
N) {
1040 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
1041 if (HST->isHVXVectorType(
N->getValueType(i),
true))
1045 if (HST->isHVXVectorType(
I.getValueType(),
true))
1051 if (HST->useHVXOps() && isHvxOp(
N)) {
1052 switch (
N->getOpcode()) {
1060 switch (
N->getOpcode()) {
1071 case HexagonISD::ADDC:
1089 std::vector<SDValue> &OutOps) {
1092 switch (ConstraintID) {
1099 OutOps.push_back(Res);
1101 OutOps.push_back(Inp);
1105 OutOps.push_back(
CurDAG->getTargetConstant(0,
SDLoc(
Op), MVT::i32));
1114 if (!U->hasOneUse())
1116 unsigned Opc = U->getOpcode();
1139 SDNode *SYNode = SY.getNode();
1143 if (LDBasePtr == STBasePtr)
1152void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {
1153 SelectionDAG &DAG = *
CurDAG;
1155 for (
auto *
I : Nodes) {
1159 auto IsSelect0 = [](
const SDValue &
Op) ->
bool {
1166 SDValue N0 =
I->getOperand(0), N1 =
I->getOperand(1);
1167 EVT VT =
I->getValueType(0);
1168 bool SelN0 = IsSelect0(N0);
1169 SDValue SOp = SelN0 ? N0 : N1;
1170 SDValue VOp = SelN0 ? N1 : N0;
1196void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {
1197 SelectionDAG &DAG = *
CurDAG;
1199 for (
auto *
I : Nodes) {
1231 if (EV % (1 << CV) != 0)
1233 unsigned DV = EV / (1 << CV);
1236 SDLoc
DL = SDLoc(
I);
1260void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {
1261 SelectionDAG &DAG = *
CurDAG;
1263 for (SDNode *
N : Nodes) {
1264 unsigned Opc =
N->getOpcode();
1301 if (TZ +
M1 + LZ != 32)
1325void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {
1326 SelectionDAG &DAG = *
CurDAG;
1328 for (SDNode *
N : Nodes) {
1329 unsigned Opc =
N->getOpcode();
1336 for (SDUse &Use :
N->uses()) {
1337 SDNode *
U =
Use.getUser();
1338 if (
U->getNumValues() != 1)
1340 EVT UVT =
U->getValueType(0);
1347 if (HST->isHLXVectorType(UVT))
1353 unsigned I1N =
Use.getOperandNo();
1355 for (
unsigned i = 0, n =
U->getNumOperands(); i != n; ++i)
1356 Ops[i] =
U->getOperand(i);
1357 EVT BVT =
Ops[I1N].getValueType();
1365 unsigned UseOpc =
U->getMachineOpcode();
1371 unsigned UseOpc =
U->getOpcode();
1393 auto getNodes = [
this]() -> std::vector<SDNode *> {
1394 std::vector<SDNode *>
T;
1395 T.reserve(
CurDAG->allnodes_size());
1401 if (HST->useHVXOps())
1402 PreprocessHvxISelDAG();
1406 ppSimplifyOrSelect0(getNodes());
1414 ppAddrReorderAddShl(getNodes());
1429 ppAddrRewriteAndSrl(getNodes());
1433 ppHoistZextI1(getNodes());
1436 dbgs() <<
"Preprocessed (Hexagon) selection DAG:";
1441 rebalanceAddressTrees();
1444 dbgs() <<
"Address tree balanced selection DAG:";
1453 if (!HFI.needsAligna(*
MF))
1456 auto &HRI = *HST.getRegisterInfo();
1457 Register AP = HRI.computeStackAlignBaseRegister(*
MF);
1458 assert(AP.
isValid() &&
"Couldn't reserve stack align register");
1466 auto &HFI = *HST->getFrameLowering();
1471 R =
CurDAG->getTargetFrameIndex(FX, MVT::i32);
1501 EVT T =
N.getValueType();
1505 R =
CurDAG->getTargetConstant(V,
SDLoc(
N),
N.getValueType());
1511 switch (
N.getOpcode()) {
1513 if (
N.getValueType() != MVT::i32)
1518 R =
CurDAG->getTargetConstant(V,
SDLoc(
N),
N.getValueType());
1521 case HexagonISD::JT:
1522 case HexagonISD::CP:
1524 if (Alignment >
Align(8))
1526 R =
N.getOperand(0);
1530 if (Alignment >
Align(1))
1536 if (Alignment >
Align(4) ||
1551 bool UseGP,
Align Alignment) {
1552 switch (
N.getOpcode()) {
1557 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1559 if (!UseGP && GAOpc != HexagonISD::CONST32)
1562 if (!
isAligned(Alignment, Const->getZExtValue()))
1567 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1568 R =
CurDAG->getTargetGlobalAddress(GA->getGlobal(),
SDLoc(Const),
1569 N.getValueType(), NewOff);
1576 case HexagonISD::CP:
1577 case HexagonISD::JT:
1578 case HexagonISD::CONST32:
1582 R =
N.getOperand(0);
1584 case HexagonISD::CONST32_GP:
1586 R =
N.getOperand(0);
1614 if (
N.getValueType() != MVT::i64)
1616 unsigned Opc =
N.getOpcode();
1622 ?
N.getOperand(0).getValueType()
1624 unsigned SW =
T.getSizeInBits();
1626 R =
N.getOperand(0);
1639 if (L->getMemoryVT().getSizeInBits() > 32)
1646 if (!S || S->getZExtValue() != 32)
1653 if (
T.getSizeInBits() == 32)
1654 R =
N.getOperand(0);
1663 EVT RT = R.getValueType();
1671 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
1672 R,
CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
1673 R,
CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
1675 SDNode *
T =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
1697 EVT RetTy =
N.getValueType();
1698 if (RetTy != MVT::i32 &&
1701 unsigned Opc =
N.getOpcode();
1709 T =
T.getVectorElementType();
1710 unsigned SW =
T.getSizeInBits();
1732 if (L->getMemoryVT().getSizeInBits() > 16)
1740 T =
T.getVectorElementType();
1741 if (
T.getSizeInBits() == 16)
1742 R =
N.getOperand(0);
1750 EVT RT = R.getValueType();
1751 if (RT == MVT::i32 ||
1762 Val =
C->getZExtValue();
1767 Val =
C->getZExtValue();
1776 Val =
C0->getZExtValue();
1777 for (
unsigned I = 1,
E =
N.getNumOperands();
I !=
E; ++
I) {
1779 if (!CI || CI->getZExtValue() != Val)
1803 EVT RetTy =
N.getValueType();
1804 if (RetTy != MVT::i32 &&
1807 unsigned Opc =
N.getOpcode();
1810 EVT T =
N.getOperand(0).getValueType();
1812 T =
T.getVectorElementType();
1813 unsigned SW =
T.getSizeInBits();
1826 if (L->getMemoryVT().getSizeInBits() > 16)
1834 T =
T.getVectorElementType();
1835 if (
T.getSizeInBits() == 16)
1836 R =
N.getOperand(0);
1854 SDValue ScalarOp =
N.getOperand(0);
1855 unsigned ScalarOpc = ScalarOp.
getOpcode();
1858 if (
T.isInteger() &&
T.getSizeInBits() <= 16) {
1864 if (
T.isInteger() &&
T.getSizeInBits() <= 16) {
1877 R =
N.getOperand(0);
1887 uint64_t ShiftVal = 0;
1897 EVT RT = R.getValueType();
1898 if (RT == MVT::i32 ||
1905bool HexagonDAGToDAGISel::keepsLowBits(
const SDValue &Val,
unsigned NumBits,
1914 if (
T.isInteger() &&
T.getSizeInBits() == NumBits) {
1925 if (
T->getVT().getSizeInBits() == NumBits) {
1935 if (
C->getZExtValue() == Mask) {
1941 if (
C->getZExtValue() == Mask) {
1953 if ((
C->getZExtValue() & Mask) == 0) {
1959 if ((
C->getZExtValue() & Mask) == 0) {
1972bool HexagonDAGToDAGISel::isAlignedMemNode(
const MemSDNode *
N)
const {
1973 return N->getAlign().value() >=
N->getMemoryVT().getStoreSize();
1976bool HexagonDAGToDAGISel::isSmallStackStore(
const StoreSDNode *
N)
const {
1977 unsigned StackSize =
MF->getFrameInfo().estimateStackSize(*
MF);
1978 switch (
N->getMemoryVT().getStoreSize()) {
1980 return StackSize <= 56;
1982 return StackSize <= 120;
1984 return StackSize <= 248;
1991bool HexagonDAGToDAGISel::isPositiveHalfWord(
const SDNode *
N)
const {
2003bool HexagonDAGToDAGISel::hasOneUse(
const SDNode *
N)
const {
2011 switch (
N->getOpcode()) {
2018 return N->getNumOperands() >= 2 &&
2026int HexagonDAGToDAGISel::getWeight(
SDNode *
N) {
2029 assert(RootWeights.count(
N) &&
"Cannot get weight of unseen root!");
2030 assert(RootWeights[
N] != -1 &&
"Cannot get weight of unvisited root!");
2031 assert(RootWeights[
N] != -2 &&
"Cannot get weight of RAWU'd root!");
2032 return RootWeights[
N];
2035int HexagonDAGToDAGISel::getHeight(
SDNode *
N) {
2038 assert(RootWeights.count(
N) && RootWeights[
N] >= 0 &&
2039 "Cannot query height of unvisited/RAUW'd node!");
2040 return RootHeights[
N];
2044struct WeightedLeaf {
2049 WeightedLeaf() =
default;
2051 WeightedLeaf(
SDValue Value,
int Weight,
int InsertionOrder) :
2052 Value(
Value), Weight(Weight), InsertionOrder(InsertionOrder) {
2053 assert(Weight >= 0 &&
"Weight must be >= 0");
2056 static bool Compare(
const WeightedLeaf &
A,
const WeightedLeaf &
B) {
2057 assert(
A.Value.getNode() &&
B.Value.getNode());
2058 return A.Weight ==
B.Weight ?
2059 (
A.InsertionOrder >
B.InsertionOrder) :
2060 (
A.Weight >
B.Weight);
2067class LeafPrioQueue {
2070 WeightedLeaf ConstElt;
2075 return (!HaveConst && Q.
empty());
2079 return Q.
size() + HaveConst;
2086 const WeightedLeaf &top() {
2092 WeightedLeaf pop() {
2097 std::pop_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
2101 void push(WeightedLeaf L,
bool SeparateConst=
true) {
2114 std::push_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
2120 void pushToBottom(WeightedLeaf L) {
2127 WeightedLeaf findSHL(
uint64_t MaxAmount);
2129 WeightedLeaf findMULbyConst();
2131 LeafPrioQueue(
unsigned Opcode) :
2132 HaveConst(
false), Opcode(Opcode) { }
2136WeightedLeaf LeafPrioQueue::findSHL(
uint64_t MaxAmount) {
2140 for (
int Pos = 0,
End = Q.
size(); Pos !=
End; ++Pos) {
2141 const WeightedLeaf &
L = Q[Pos];
2148 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
2155 if (
Result.Value.getNode()) {
2156 Q.
erase(&Q[ResultPos]);
2157 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
2163WeightedLeaf LeafPrioQueue::findMULbyConst() {
2167 for (
int Pos = 0,
End = Q.
size(); Pos !=
End; ++Pos) {
2168 const WeightedLeaf &
L = Q[Pos];
2175 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
2182 if (
Result.Value.getNode()) {
2183 Q.
erase(&Q[ResultPos]);
2184 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
2191 if (
N->getNumOperands() < 2)
2193 uint64_t MulFactor = 1ull <<
N->getConstantOperandVal(1);
2194 return CurDAG->getConstant(MulFactor, SDLoc(
N),
2195 N->getOperand(1).getValueType());
2203 unsigned MaxFactor = 0;
2204 for (
int i = 0; i < 2; ++i) {
2208 const APInt &CInt =
C->getAPIntValue();
2227 if (
V.getNumOperands() < 2)
2230 for (
int i = 0; i < 2; ++i)
2232 V.getConstantOperandVal(i) % (1ULL << Amount) == 0) {
2233 uint64_t NewConst =
V.getConstantOperandVal(i) >> Amount;
2234 return (NewConst == 1);
2237 if (
V.getNumOperands() < 2 ||
2240 return (Amount ==
V.getConstantOperandVal(1));
2246SDValue HexagonDAGToDAGISel::factorOutPowerOf2(
SDValue V,
unsigned Power) {
2248 if (
V.getNumOperands() < 2)
2253 for (
int i=0; i < 2; ++i) {
2255 V.getConstantOperandVal(i) % ((
uint64_t)1 << Power) == 0) {
2256 uint64_t NewConst =
V.getConstantOperandVal(i) >> Power;
2260 SDLoc(
V),
V.getValueType());
2267 uint64_t ShiftAmount =
V.getConstantOperandVal(1);
2268 if (ShiftAmount == Power)
2270 Ops[1] =
CurDAG->getConstant(ShiftAmount - Power,
2271 SDLoc(
V),
V.getValueType());
2274 return CurDAG->getNode(
V.getOpcode(), SDLoc(
V),
V.getValueType(),
Ops);
2278 return V.getOpcode() == HexagonISD::CONST32 ||
2279 V.getOpcode() == HexagonISD::CONST32_GP;
2282unsigned HexagonDAGToDAGISel::getUsesInFunction(
const Value *
V) {
2283 auto [It,
Inserted] = GAUsesInFunction.try_emplace(
V);
2288 const Function &CurF =
CurDAG->getMachineFunction().getFunction();
2289 for (
const User *U :
V->users()) {
2305SDValue HexagonDAGToDAGISel::balanceSubTree(
SDNode *
N,
bool TopLevel) {
2306 assert(RootWeights.count(
N) &&
"Cannot balance non-root node.");
2307 assert(RootWeights[
N] != -2 &&
"This node was RAUW'd!");
2311 if (RootWeights[
N] != -1)
2316 if (
N->getNumOperands() < 2)
2328 Weight = getWeight(balanceSubTree(Op0N).
getNode());
2331 Weight = getWeight(Op0N);
2335 Weight += getWeight(balanceSubTree(Op1N).
getNode());
2338 Weight += getWeight(Op1N);
2340 RootWeights[
N] = Weight;
2344 int Height0 = 0, Height1 = 0;
2346 RootWeights[Op0N] >= 0)
2347 Height0 = getHeight(Op0N);
2349 RootWeights[Op1N] >= 0)
2350 Height1 = getHeight(Op1N);
2352 RootHeights[
N] = std::max(Height0, Height1) + 1;
2354 LLVM_DEBUG(
dbgs() <<
"--> No need to balance root (Weight=" << Weight
2355 <<
" Height=" << RootHeights[
N] <<
"): ");
2364 unsigned NOpcode =
N->getOpcode();
2366 LeafPrioQueue Leaves(NOpcode);
2374 bool CanFactorize =
false;
2375 WeightedLeaf Mul1, Mul2;
2376 unsigned MaxPowerOf2 = 0;
2381 bool HaveTopLevelShift =
false;
2387 HaveTopLevelShift =
true;
2391 int InsertionOrder = 0;
2392 SmallDenseMap<SDValue, int> NodeHeights;
2393 bool Imbalanced =
false;
2394 int CurrentWeight = 0;
2395 while (!Worklist.
empty()) {
2401 int Weight = RootWeights[Child.
getNode()];
2403 Child = balanceSubTree(Child.
getNode());
2405 Weight = getWeight(Child.
getNode());
2406 }
else if (Weight == -2) {
2411 return balanceSubTree(
N, TopLevel);
2414 NodeHeights[Child] = 1;
2415 CurrentWeight += Weight;
2418 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&
2425 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);
2426 MaxPowerOf2 = PowerOf2;
2428 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);
2429 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);
2432 if (MaxPowerOf2 > 3)
2435 CanFactorize =
true;
2438 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2441 int Weight = getWeight(Child.
getNode());
2443 NodeHeights[Child] = getHeight(Child.
getNode());
2444 CurrentWeight += Weight;
2447 GA = WeightedLeaf(Child, Weight, InsertionOrder++);
2449 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2453 unsigned ChildOpcode = Child.
getOpcode();
2454 assert(ChildOpcode == NOpcode ||
2459 int Weight = getWeight(Child.
getNode());
2460 NodeHeights[Child] = getHeight(Child.
getNode());
2461 CurrentWeight += Weight;
2462 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2469 Op1 = getMultiplierForSHL(Child.
getNode());
2470 assert(Op1.
getNode() &&
"getMultiplierForSHL returned null");
2475 assert(!NodeHeights.
count(Child) &&
"Parent visited before children?");
2482 if (std::abs(NodeHeights[Op1] - NodeHeights[Child->
getOperand(0)]) > 1)
2485 NodeHeights[Child] = std::max(NodeHeights[Op1],
2492 <<
" weight=" << CurrentWeight
2493 <<
" imbalanced=" << Imbalanced <<
"\n");
2499 LLVM_DEBUG(
dbgs() <<
"--> Found common factor for two MUL children!\n");
2500 int Weight = Mul1.Weight + Mul2.Weight;
2501 int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;
2502 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);
2503 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);
2505 Mul1Factored, Mul2Factored);
2510 NodeHeights[
New] = Height;
2511 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));
2512 }
else if (Mul1.Value.
getNode()) {
2518 CanFactorize =
false;
2524 bool CombinedGA =
false;
2528 GlobalAddressSDNode *GANode =
2532 if (getUsesInFunction(GANode->
getGlobal()) == 1 &&
Offset->hasOneUse() &&
2535 <<
Offset->getSExtValue() <<
"): ");
2544 GA.Weight += Leaves.top().Weight;
2546 NodeHeights[GA.Value] = getHeight(GA.Value.
getNode());
2555 RootWeights[
N] = CurrentWeight;
2556 RootHeights[
N] = NodeHeights[
SDValue(
N, 0)];
2563 WeightedLeaf
SHL = Leaves.findSHL(31);
2564 if (
SHL.Value.getNode()) {
2565 int Height = std::max(NodeHeights[GA.Value], NodeHeights[
SHL.Value]) + 1;
2568 GA.Value,
SHL.Value);
2569 GA.Weight =
SHL.Weight;
2570 NodeHeights[GA.Value] = Height;
2579 if (TopLevel && !CanFactorize && Leaves.hasConst()) {
2581 Leaves.pushToBottom(Leaves.pop());
2584 const DataLayout &
DL =
CurDAG->getDataLayout();
2588 while (Leaves.size() > 1) {
2589 WeightedLeaf L0 = Leaves.pop();
2593 WeightedLeaf L1 = Leaves.findMULbyConst();
2597 assert(L0.Weight <= L1.Weight &&
"Priority queue is broken!");
2600 int V0Weight = L0.Weight;
2602 int V1Weight = L1.Weight;
2605 if ((RootWeights.count(
V0.getNode()) && RootWeights[
V0.getNode()] == -2) ||
2606 (RootWeights.count(
V1.getNode()) && RootWeights[
V1.getNode()] == -2)) {
2608 return balanceSubTree(
N, TopLevel);
2613 EVT VT =
N->getValueType(0);
2623 "Children must have been visited before re-combining them!");
2624 int Height = std::max(NodeHeights[V0], NodeHeights[
V1]) + 1;
2628 NewNode =
CurDAG->getNode(
2632 TLI.getScalarShiftAmountTy(
DL,
V0.getValueType())));
2634 NewNode =
CurDAG->getNode(NOpcode, SDLoc(
N), VT, V0,
V1);
2636 NodeHeights[NewNode] = Height;
2638 int Weight = V0Weight + V1Weight;
2639 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));
2642 <<
",Height=" << Height <<
"):\n");
2646 assert(Leaves.size() == 1);
2647 SDValue NewRoot = Leaves.top().Value;
2650 int Height = NodeHeights[NewRoot];
2658 NewRoot =
CurDAG->getNode(
2662 TLI.getScalarShiftAmountTy(
DL,
V0.getValueType())));
2673 RootWeights[
N] = -2;
2678 RootWeights[NewRoot.
getNode()] = Leaves.top().Weight;
2679 RootHeights[NewRoot.
getNode()] = Height;
2684void HexagonDAGToDAGISel::rebalanceAddressTrees() {
2695 if (RootWeights.count(
BasePtr.getNode()))
2698 LLVM_DEBUG(
dbgs() <<
"** Rebalancing address calculation in node: ");
2704 if (
BasePtr->getNumOperands() < 2)
2710 while (!Worklist.
empty()) {
2712 unsigned Opcode =
N->getOpcode();
2717 if (
N->getNumOperands() < 2)
2720 Worklist.
push_back(
N->getOperand(0).getNode());
2721 Worklist.
push_back(
N->getOperand(1).getNode());
2724 if (
N->hasOneUse() && Opcode ==
N->user_begin()->getOpcode())
2728 RootWeights.try_emplace(
N, -1);
2732 RootWeights[
BasePtr.getNode()] = -1;
2736 if (
N->getNumOperands() >= 3)
2737 N =
CurDAG->UpdateNodeOperands(
N,
N->getOperand(0), NewBasePtr,
2740 if (
N->getNumOperands() >= 4)
2741 N =
CurDAG->UpdateNodeOperands(
N,
N->getOperand(0),
N->getOperand(1),
2742 NewBasePtr,
N->getOperand(3));
2749 CurDAG->RemoveDeadNodes();
2750 GAUsesInFunction.clear();
2751 RootHeights.clear();
2752 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool willShiftRightEliminate(SDValue V, unsigned Amount)
static SDValue getCircRegister(SelectionDAG &DAG, SDLoc DL, SDNode *N, unsigned MOp, unsigned CSOp)
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 bool getConstantSplatValue(SDValue N, uint64_t &Val)
Return the constant value of a node if it is a ConstantSDNode, or if it is a SPLAT_VECTOR / BUILD_VEC...
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)
bool DetectUseZxth(SDValue &N, SDValue &R)
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 DetectUseSxth(SDValue &N, SDValue &R)
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 alignment of this function's frame.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
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, in exactly one operand.
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
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
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.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
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.
@ 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).
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ 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...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
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.
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.
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...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned M1(unsigned Val)
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...
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.
@ End
Run the machine verifier once, at the end of the pipeline.
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.
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 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.