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) {
1204 SDValue
Off =
I->getOperand(2);
1209 SDValue T0 =
Off.getOperand(1);
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();
1267 SDValue Addr =
Opc ==
ISD::LOAD ?
N->getOperand(1) :
N->getOperand(2);
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();
1332 SDValue OpI1 =
N->getOperand(0);
1336 for (SDUse &Use :
N->uses()) {
1337 SDNode *
U =
Use.getUser();
1338 if (
U->getNumValues() != 1)
1340 EVT UVT =
U->getValueType(0);
1350 unsigned I1N =
Use.getOperandNo();
1352 for (
unsigned i = 0, n =
U->getNumOperands(); i != n; ++i)
1353 Ops[i] =
U->getOperand(i);
1354 EVT BVT =
Ops[I1N].getValueType();
1362 unsigned UseOpc =
U->getMachineOpcode();
1368 unsigned UseOpc =
U->getOpcode();
1390 auto getNodes = [
this]() -> std::vector<SDNode *> {
1391 std::vector<SDNode *>
T;
1392 T.reserve(
CurDAG->allnodes_size());
1398 if (HST->useHVXOps())
1399 PreprocessHvxISelDAG();
1403 ppSimplifyOrSelect0(getNodes());
1411 ppAddrReorderAddShl(getNodes());
1426 ppAddrRewriteAndSrl(getNodes());
1430 ppHoistZextI1(getNodes());
1433 dbgs() <<
"Preprocessed (Hexagon) selection DAG:";
1438 rebalanceAddressTrees();
1441 dbgs() <<
"Address tree balanced selection DAG:";
1450 if (!HFI.needsAligna(*
MF))
1453 auto &HRI = *HST.getRegisterInfo();
1454 Register AP = HRI.computeStackAlignBaseRegister(*
MF);
1455 assert(AP.
isValid() &&
"Couldn't reserve stack align register");
1463 auto &HFI = *HST->getFrameLowering();
1468 R =
CurDAG->getTargetFrameIndex(FX, MVT::i32);
1498 EVT T =
N.getValueType();
1502 R =
CurDAG->getTargetConstant(V,
SDLoc(
N),
N.getValueType());
1508 switch (
N.getOpcode()) {
1510 if (
N.getValueType() != MVT::i32)
1515 R =
CurDAG->getTargetConstant(V,
SDLoc(
N),
N.getValueType());
1518 case HexagonISD::JT:
1519 case HexagonISD::CP:
1521 if (Alignment >
Align(8))
1523 R =
N.getOperand(0);
1527 if (Alignment >
Align(1))
1533 if (Alignment >
Align(4) ||
1548 bool UseGP,
Align Alignment) {
1549 switch (
N.getOpcode()) {
1554 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1556 if (!UseGP && GAOpc != HexagonISD::CONST32)
1559 if (!
isAligned(Alignment, Const->getZExtValue()))
1564 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1565 R =
CurDAG->getTargetGlobalAddress(GA->getGlobal(),
SDLoc(Const),
1566 N.getValueType(), NewOff);
1573 case HexagonISD::CP:
1574 case HexagonISD::JT:
1575 case HexagonISD::CONST32:
1579 R =
N.getOperand(0);
1581 case HexagonISD::CONST32_GP:
1583 R =
N.getOperand(0);
1611 if (
N.getValueType() != MVT::i64)
1613 unsigned Opc =
N.getOpcode();
1619 ?
N.getOperand(0).getValueType()
1621 unsigned SW =
T.getSizeInBits();
1623 R =
N.getOperand(0);
1636 if (L->getMemoryVT().getSizeInBits() > 32)
1643 if (!S || S->getZExtValue() != 32)
1650 if (
T.getSizeInBits() == 32)
1651 R =
N.getOperand(0);
1660 EVT RT = R.getValueType();
1668 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
1669 R,
CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
1670 R,
CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
1672 SDNode *
T =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
1678bool HexagonDAGToDAGISel::keepsLowBits(
const SDValue &Val,
unsigned NumBits,
1687 if (
T.isInteger() &&
T.getSizeInBits() == NumBits) {
1698 if (
T->getVT().getSizeInBits() == NumBits) {
1708 if (
C->getZExtValue() == Mask) {
1714 if (
C->getZExtValue() == Mask) {
1726 if ((
C->getZExtValue() & Mask) == 0) {
1732 if ((
C->getZExtValue() & Mask) == 0) {
1745bool HexagonDAGToDAGISel::isAlignedMemNode(
const MemSDNode *
N)
const {
1746 return N->getAlign().value() >=
N->getMemoryVT().getStoreSize();
1749bool HexagonDAGToDAGISel::isSmallStackStore(
const StoreSDNode *
N)
const {
1750 unsigned StackSize =
MF->getFrameInfo().estimateStackSize(*
MF);
1751 switch (
N->getMemoryVT().getStoreSize()) {
1753 return StackSize <= 56;
1755 return StackSize <= 120;
1757 return StackSize <= 248;
1764bool HexagonDAGToDAGISel::isPositiveHalfWord(
const SDNode *
N)
const {
1776bool HexagonDAGToDAGISel::hasOneUse(
const SDNode *
N)
const {
1784 switch (
N->getOpcode()) {
1791 return N->getNumOperands() >= 2 &&
1799int HexagonDAGToDAGISel::getWeight(
SDNode *
N) {
1802 assert(RootWeights.count(
N) &&
"Cannot get weight of unseen root!");
1803 assert(RootWeights[
N] != -1 &&
"Cannot get weight of unvisited root!");
1804 assert(RootWeights[
N] != -2 &&
"Cannot get weight of RAWU'd root!");
1805 return RootWeights[
N];
1808int HexagonDAGToDAGISel::getHeight(
SDNode *
N) {
1811 assert(RootWeights.count(
N) && RootWeights[
N] >= 0 &&
1812 "Cannot query height of unvisited/RAUW'd node!");
1813 return RootHeights[
N];
1817struct WeightedLeaf {
1822 WeightedLeaf() =
default;
1824 WeightedLeaf(SDValue
Value,
int Weight,
int InsertionOrder) :
1825 Value(
Value), Weight(Weight), InsertionOrder(InsertionOrder) {
1826 assert(Weight >= 0 &&
"Weight must be >= 0");
1829 static bool Compare(
const WeightedLeaf &
A,
const WeightedLeaf &
B) {
1830 assert(
A.Value.getNode() &&
B.Value.getNode());
1831 return A.Weight ==
B.Weight ?
1832 (
A.InsertionOrder >
B.InsertionOrder) :
1833 (
A.Weight >
B.Weight);
1840class LeafPrioQueue {
1843 WeightedLeaf ConstElt;
1848 return (!HaveConst && Q.
empty());
1852 return Q.
size() + HaveConst;
1859 const WeightedLeaf &top() {
1865 WeightedLeaf pop() {
1870 std::pop_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1874 void push(WeightedLeaf L,
bool SeparateConst=
true) {
1887 std::push_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1893 void pushToBottom(WeightedLeaf L) {
1900 WeightedLeaf findSHL(
uint64_t MaxAmount);
1902 WeightedLeaf findMULbyConst();
1904 LeafPrioQueue(
unsigned Opcode) :
1905 HaveConst(
false), Opcode(Opcode) { }
1909WeightedLeaf LeafPrioQueue::findSHL(
uint64_t MaxAmount) {
1913 for (
int Pos = 0,
End = Q.
size(); Pos !=
End; ++Pos) {
1914 const WeightedLeaf &
L = Q[Pos];
1921 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1928 if (
Result.Value.getNode()) {
1929 Q.
erase(&Q[ResultPos]);
1930 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1936WeightedLeaf LeafPrioQueue::findMULbyConst() {
1940 for (
int Pos = 0,
End = Q.
size(); Pos !=
End; ++Pos) {
1941 const WeightedLeaf &
L = Q[Pos];
1948 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1955 if (
Result.Value.getNode()) {
1956 Q.
erase(&Q[ResultPos]);
1957 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1964 if (
N->getNumOperands() < 2)
1966 uint64_t MulFactor = 1ull <<
N->getConstantOperandVal(1);
1967 return CurDAG->getConstant(MulFactor, SDLoc(
N),
1968 N->getOperand(1).getValueType());
1976 unsigned MaxFactor = 0;
1977 for (
int i = 0; i < 2; ++i) {
1981 const APInt &CInt =
C->getAPIntValue();
2000 if (V.getNumOperands() < 2)
2002 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
2003 for (
int i = 0; i < 2; ++i)
2005 V.getConstantOperandVal(i) % (1ULL << Amount) == 0) {
2006 uint64_t NewConst = V.getConstantOperandVal(i) >> Amount;
2007 return (NewConst == 1);
2009 }
else if (V.getOpcode() ==
ISD::SHL) {
2010 if (V.getNumOperands() < 2 ||
2013 return (Amount == V.getConstantOperandVal(1));
2019SDValue HexagonDAGToDAGISel::factorOutPowerOf2(
SDValue V,
unsigned Power) {
2021 if (
V.getNumOperands() < 2)
2024 SDValue
Ops[] = {
V.getOperand(0),
V.getOperand(1) };
2026 for (
int i=0; i < 2; ++i) {
2028 V.getConstantOperandVal(i) % ((
uint64_t)1 << Power) == 0) {
2029 uint64_t NewConst =
V.getConstantOperandVal(i) >> Power;
2033 SDLoc(V),
V.getValueType());
2040 uint64_t ShiftAmount =
V.getConstantOperandVal(1);
2041 if (ShiftAmount == Power)
2043 Ops[1] =
CurDAG->getConstant(ShiftAmount - Power,
2044 SDLoc(V),
V.getValueType());
2047 return CurDAG->getNode(
V.getOpcode(), SDLoc(V),
V.getValueType(),
Ops);
2051 return V.getOpcode() == HexagonISD::CONST32 ||
2052 V.getOpcode() == HexagonISD::CONST32_GP;
2055unsigned HexagonDAGToDAGISel::getUsesInFunction(
const Value *V) {
2056 auto [It,
Inserted] = GAUsesInFunction.try_emplace(V);
2061 const Function &CurF =
CurDAG->getMachineFunction().getFunction();
2062 for (
const User *U :
V->users()) {
2078SDValue HexagonDAGToDAGISel::balanceSubTree(
SDNode *
N,
bool TopLevel) {
2079 assert(RootWeights.count(
N) &&
"Cannot balance non-root node.");
2080 assert(RootWeights[
N] != -2 &&
"This node was RAUW'd!");
2084 if (RootWeights[
N] != -1)
2085 return SDValue(
N, 0);
2089 if (
N->getNumOperands() < 2)
2090 return SDValue(
N, 0);
2101 Weight = getWeight(balanceSubTree(Op0N).
getNode());
2104 Weight = getWeight(Op0N);
2108 Weight += getWeight(balanceSubTree(Op1N).
getNode());
2111 Weight += getWeight(Op1N);
2113 RootWeights[
N] = Weight;
2117 int Height0 = 0, Height1 = 0;
2119 RootWeights[Op0N] >= 0)
2120 Height0 = getHeight(Op0N);
2122 RootWeights[Op1N] >= 0)
2123 Height1 = getHeight(Op1N);
2125 RootHeights[
N] = std::max(Height0, Height1) + 1;
2127 LLVM_DEBUG(
dbgs() <<
"--> No need to balance root (Weight=" << Weight
2128 <<
" Height=" << RootHeights[
N] <<
"): ");
2131 return SDValue(
N, 0);
2137 unsigned NOpcode =
N->getOpcode();
2139 LeafPrioQueue Leaves(NOpcode);
2147 bool CanFactorize =
false;
2148 WeightedLeaf Mul1, Mul2;
2149 unsigned MaxPowerOf2 = 0;
2154 bool HaveTopLevelShift =
false;
2160 HaveTopLevelShift =
true;
2164 int InsertionOrder = 0;
2165 SmallDenseMap<SDValue, int> NodeHeights;
2166 bool Imbalanced =
false;
2167 int CurrentWeight = 0;
2168 while (!Worklist.
empty()) {
2174 int Weight = RootWeights[Child.
getNode()];
2176 Child = balanceSubTree(Child.
getNode());
2178 Weight = getWeight(Child.
getNode());
2179 }
else if (Weight == -2) {
2184 return balanceSubTree(
N, TopLevel);
2187 NodeHeights[Child] = 1;
2188 CurrentWeight += Weight;
2191 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&
2198 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);
2199 MaxPowerOf2 = PowerOf2;
2201 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);
2202 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);
2205 if (MaxPowerOf2 > 3)
2208 CanFactorize =
true;
2211 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2214 int Weight = getWeight(Child.
getNode());
2216 NodeHeights[Child] = getHeight(Child.
getNode());
2217 CurrentWeight += Weight;
2220 GA = WeightedLeaf(Child, Weight, InsertionOrder++);
2222 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2226 unsigned ChildOpcode = Child.
getOpcode();
2227 assert(ChildOpcode == NOpcode ||
2232 int Weight = getWeight(Child.
getNode());
2233 NodeHeights[Child] = getHeight(Child.
getNode());
2234 CurrentWeight += Weight;
2235 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2242 Op1 = getMultiplierForSHL(Child.
getNode());
2243 assert(Op1.
getNode() &&
"getMultiplierForSHL returned null");
2248 assert(!NodeHeights.
count(Child) &&
"Parent visited before children?");
2255 if (std::abs(NodeHeights[Op1] - NodeHeights[Child->
getOperand(0)]) > 1)
2258 NodeHeights[Child] = std::max(NodeHeights[Op1],
2264 LLVM_DEBUG(
dbgs() <<
"--> Current height=" << NodeHeights[SDValue(
N, 0)]
2265 <<
" weight=" << CurrentWeight
2266 <<
" imbalanced=" << Imbalanced <<
"\n");
2272 LLVM_DEBUG(
dbgs() <<
"--> Found common factor for two MUL children!\n");
2273 int Weight = Mul1.Weight + Mul2.Weight;
2274 int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;
2275 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);
2276 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);
2278 Mul1Factored, Mul2Factored);
2279 SDValue
Const =
CurDAG->getConstant(MaxPowerOf2, SDLoc(
N),
2283 NodeHeights[
New] = Height;
2284 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));
2285 }
else if (Mul1.Value.
getNode()) {
2291 CanFactorize =
false;
2297 bool CombinedGA =
false;
2301 GlobalAddressSDNode *GANode =
2305 if (getUsesInFunction(GANode->
getGlobal()) == 1 &&
Offset->hasOneUse() &&
2308 <<
Offset->getSExtValue() <<
"): ");
2317 GA.Weight += Leaves.top().Weight;
2319 NodeHeights[GA.Value] = getHeight(GA.Value.
getNode());
2328 RootWeights[
N] = CurrentWeight;
2329 RootHeights[
N] = NodeHeights[SDValue(
N, 0)];
2331 return SDValue(
N, 0);
2336 WeightedLeaf
SHL = Leaves.findSHL(31);
2337 if (
SHL.Value.getNode()) {
2338 int Height = std::max(NodeHeights[GA.Value], NodeHeights[
SHL.Value]) + 1;
2341 GA.Value,
SHL.Value);
2342 GA.Weight =
SHL.Weight;
2343 NodeHeights[GA.Value] = Height;
2352 if (TopLevel && !CanFactorize && Leaves.hasConst()) {
2354 Leaves.pushToBottom(Leaves.pop());
2357 const DataLayout &
DL =
CurDAG->getDataLayout();
2361 while (Leaves.size() > 1) {
2362 WeightedLeaf L0 = Leaves.pop();
2366 WeightedLeaf L1 = Leaves.findMULbyConst();
2370 assert(L0.Weight <= L1.Weight &&
"Priority queue is broken!");
2372 SDValue
V0 = L0.Value;
2373 int V0Weight = L0.Weight;
2374 SDValue
V1 = L1.Value;
2375 int V1Weight = L1.Weight;
2378 if ((RootWeights.count(
V0.getNode()) && RootWeights[
V0.getNode()] == -2) ||
2379 (RootWeights.count(
V1.getNode()) && RootWeights[
V1.getNode()] == -2)) {
2381 return balanceSubTree(
N, TopLevel);
2386 EVT VT =
N->getValueType(0);
2396 "Children must have been visited before re-combining them!");
2397 int Height = std::max(NodeHeights[V0], NodeHeights[
V1]) + 1;
2401 NewNode =
CurDAG->getNode(
2405 TLI.getScalarShiftAmountTy(
DL,
V0.getValueType())));
2407 NewNode =
CurDAG->getNode(NOpcode, SDLoc(
N), VT, V0,
V1);
2409 NodeHeights[NewNode] = Height;
2411 int Weight = V0Weight + V1Weight;
2412 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));
2415 <<
",Height=" << Height <<
"):\n");
2419 assert(Leaves.size() == 1);
2420 SDValue NewRoot = Leaves.top().Value;
2423 int Height = NodeHeights[NewRoot];
2431 NewRoot =
CurDAG->getNode(
2435 TLI.getScalarShiftAmountTy(
DL,
V0.getValueType())));
2446 RootWeights[
N] = -2;
2451 RootWeights[NewRoot.
getNode()] = Leaves.top().Weight;
2452 RootHeights[NewRoot.
getNode()] = Height;
2457void HexagonDAGToDAGISel::rebalanceAddressTrees() {
2468 if (RootWeights.count(
BasePtr.getNode()))
2471 LLVM_DEBUG(
dbgs() <<
"** Rebalancing address calculation in node: ");
2477 if (
BasePtr->getNumOperands() < 2)
2483 while (!Worklist.
empty()) {
2485 unsigned Opcode =
N->getOpcode();
2490 if (
N->getNumOperands() < 2)
2493 Worklist.
push_back(
N->getOperand(0).getNode());
2494 Worklist.
push_back(
N->getOperand(1).getNode());
2497 if (
N->hasOneUse() && Opcode ==
N->user_begin()->getOpcode())
2501 RootWeights.try_emplace(
N, -1);
2505 RootWeights[
BasePtr.getNode()] = -1;
2506 SDValue NewBasePtr = balanceSubTree(
BasePtr.getNode(),
true);
2509 if (
N->getNumOperands() >= 3)
2510 N =
CurDAG->UpdateNodeOperands(
N,
N->getOperand(0), NewBasePtr,
2513 if (
N->getNumOperands() >= 4)
2514 N =
CurDAG->UpdateNodeOperands(
N,
N->getOperand(0),
N->getOperand(1),
2515 NewBasePtr,
N->getOperand(3));
2522 CurDAG->RemoveDeadNodes();
2523 GAUsesInFunction.clear();
2524 RootHeights.clear();
2525 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< 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 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 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).
@ 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.
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 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.