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();
797 assert(AR.isValid() &&
"Missing stack align base register");
800 R =
CurDAG->getMachineNode(Hexagon::PS_fia,
DL, MVT::i32,
Ops);
807 unsigned OpcCarry =
N->getOpcode() == HexagonISD::ADDC ? Hexagon::A4_addp_c
808 : Hexagon::A4_subp_c;
810 { N->getOperand(0), N->getOperand(1),
816 MVT ResTy =
N->getValueType(0).getSimpleVT();
817 if (HST->isHVXVectorType(ResTy,
true))
818 return SelectHvxVAlign(
N);
824 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
826 CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
828 CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
830 SDNode *R =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
837 if (HST->useCompound()) {
838 C =
CurDAG->getMachineNode(Hexagon::S4_andi_asl_ri, dl, MVT::i32,
839 M0,
N->getOperand(2),
M1);
841 SDNode *
T =
CurDAG->getMachineNode(Hexagon::S2_asl_i_r, dl, MVT::i32,
842 N->getOperand(2),
M1);
843 C =
CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
846 SDNode *S =
CurDAG->getMachineNode(Hexagon::S2_lsr_r_p, dl, MVT::i64,
848 SDValue E =
CurDAG->getTargetExtractSubreg(Hexagon::isub_lo, dl, ResTy,
853 SDNode *Pu =
CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::v8i1,
855 SDNode *VA =
CurDAG->getMachineNode(Hexagon::S2_valignrb, dl, ResTy,
856 N->getOperand(0),
N->getOperand(1),
869 SDNode *
AA =
CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
870 N->getOperand(0), M);
879 MVT OpTy =
Op.getValueType().getSimpleVT();
886 MVT ResTy =
N->getValueType(0).getSimpleVT();
894 MVT ResTy =
N->getValueType(0).getSimpleVT();
896 SDNode *
T =
CurDAG->getMachineNode(Hexagon::A4_vcmpbgtui, dl, ResTy,
897 N->getOperand(0), Zero);
903 MVT ResTy =
N->getValueType(0).getSimpleVT();
905 MVT OpTy =
N->getOperand(0).getValueType().getSimpleVT(); (void)
OpTy;
906 assert(HST->getVectorLength() * 8 ==
OpTy.getSizeInBits());
909 SDNode *R =
CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
C);
910 SDNode *
T =
CurDAG->getMachineNode(Hexagon::V6_vandvrt, dl, ResTy,
917 MVT ResTy =
N->getValueType(0).getSimpleVT();
922 SDNode *R =
CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
C);
923 SDNode *
T =
CurDAG->getMachineNode(Hexagon::V6_vandqrt, dl, ResTy,
932 Ops = {
N->getOperand(0),
N->getOperand(1)};
934 VTs =
CurDAG->getVTList(MVT::f32, MVT::f32);
935 SDNode *ResScale =
CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs,
Ops);
936 SDNode *
D =
CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32,
Ops);
940 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32,
C);
942 SDNode *n =
CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32,
Ops);
943 SDNode *Err =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
946 SDNode *NewRec =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
949 SDNode *newErr =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
953 Hexagon::A2_andir, dl, MVT::f32,
SDValue(n, 0),
954 CurDAG->getTargetConstant(0x80000000, dl, MVT::i32));
956 CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(q, 0),
959 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
962 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
SDValue(n, 0),
964 SDNode *NNewQ =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
969 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
SDValue(n, 0),
971 std::array<SDValue, 4> temp1 = {
SDValue(NNewQ, 0),
SDValue(NqErr, 0),
975 CurDAG->getMachineNode(Hexagon::F2_sffma_sc, dl, MVT::f32, OpValue1);
983 Ops = {
N->getOperand(0),
N->getOperand(1)};
985 VTs =
CurDAG->getVTList(MVT::f32, MVT::f32);
986 SDNode *ResScale =
CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs,
Ops);
987 SDNode *
D =
CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32,
Ops);
991 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32,
C);
993 SDNode *n =
CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32,
Ops);
994 SDNode *Err =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
997 SDNode *NewRec =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
1000 SDNode *newErr =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
1005 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
1008 Hexagon::F2_sfmpy, dl, MVT::f32,
SDValue(NNewRec, 0),
SDValue(n, 0));
1013 if (
N->getFlags().hasAllowReassociation())
1020 if (
N->isMachineOpcode())
1021 return N->setNodeId(-1);
1023 auto isHvxOp = [
this](
SDNode *
N) {
1024 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
1025 if (HST->isHVXVectorType(
N->getValueType(i),
true))
1029 if (HST->isHVXVectorType(
I.getValueType(),
true))
1035 if (HST->useHVXOps() && isHvxOp(
N)) {
1036 switch (
N->getOpcode()) {
1044 switch (
N->getOpcode()) {
1055 case HexagonISD::ADDC:
1073 std::vector<SDValue> &OutOps) {
1076 switch (ConstraintID) {
1083 OutOps.push_back(Res);
1085 OutOps.push_back(Inp);
1089 OutOps.push_back(
CurDAG->getTargetConstant(0,
SDLoc(
Op), MVT::i32));
1098 if (!U->hasOneUse())
1100 unsigned Opc = U->getOpcode();
1123 SDNode *SYNode = SY.getNode();
1127 if (LDBasePtr == STBasePtr)
1136void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {
1137 SelectionDAG &DAG = *
CurDAG;
1139 for (
auto *
I : Nodes) {
1143 auto IsSelect0 = [](
const SDValue &
Op) ->
bool {
1150 SDValue N0 =
I->getOperand(0), N1 =
I->getOperand(1);
1151 EVT VT =
I->getValueType(0);
1152 bool SelN0 = IsSelect0(N0);
1153 SDValue SOp = SelN0 ? N0 : N1;
1154 SDValue VOp = SelN0 ? N1 : N0;
1180void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {
1181 SelectionDAG &DAG = *
CurDAG;
1183 for (
auto *
I : Nodes) {
1215 if (EV % (1 << CV) != 0)
1217 unsigned DV = EV / (1 << CV);
1220 SDLoc
DL = SDLoc(
I);
1244void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {
1245 SelectionDAG &DAG = *
CurDAG;
1247 for (SDNode *
N : Nodes) {
1248 unsigned Opc =
N->getOpcode();
1285 if (TZ +
M1 + LZ != 32)
1309void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {
1310 SelectionDAG &DAG = *
CurDAG;
1312 for (SDNode *
N : Nodes) {
1313 unsigned Opc =
N->getOpcode();
1320 for (SDUse &Use :
N->uses()) {
1321 SDNode *
U =
Use.getUser();
1322 if (
U->getNumValues() != 1)
1324 EVT UVT =
U->getValueType(0);
1334 unsigned I1N =
Use.getOperandNo();
1336 for (
unsigned i = 0, n =
U->getNumOperands(); i != n; ++i)
1337 Ops[i] =
U->getOperand(i);
1338 EVT BVT =
Ops[I1N].getValueType();
1346 unsigned UseOpc =
U->getMachineOpcode();
1352 unsigned UseOpc =
U->getOpcode();
1374 auto getNodes = [
this]() -> std::vector<SDNode *> {
1375 std::vector<SDNode *>
T;
1376 T.reserve(
CurDAG->allnodes_size());
1382 if (HST->useHVXOps())
1383 PreprocessHvxISelDAG();
1387 ppSimplifyOrSelect0(getNodes());
1395 ppAddrReorderAddShl(getNodes());
1410 ppAddrRewriteAndSrl(getNodes());
1414 ppHoistZextI1(getNodes());
1417 dbgs() <<
"Preprocessed (Hexagon) selection DAG:";
1422 rebalanceAddressTrees();
1425 dbgs() <<
"Address tree balanced selection DAG:";
1434 if (!HFI.needsAligna(*
MF))
1437 auto &HRI = *HST.getRegisterInfo();
1438 Register AP = HRI.computeStackAlignBaseRegister(*
MF);
1439 assert(AP.
isValid() &&
"Couldn't reserve stack align register");
1447 auto &HFI = *HST->getFrameLowering();
1452 R =
CurDAG->getTargetFrameIndex(FX, MVT::i32);
1482 EVT T =
N.getValueType();
1486 R =
CurDAG->getTargetConstant(V,
SDLoc(
N),
N.getValueType());
1492 switch (
N.getOpcode()) {
1494 if (
N.getValueType() != MVT::i32)
1499 R =
CurDAG->getTargetConstant(V,
SDLoc(
N),
N.getValueType());
1502 case HexagonISD::JT:
1503 case HexagonISD::CP:
1505 if (Alignment >
Align(8))
1507 R =
N.getOperand(0);
1511 if (Alignment >
Align(1))
1517 if (Alignment >
Align(4) ||
1532 bool UseGP,
Align Alignment) {
1533 switch (
N.getOpcode()) {
1538 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1540 if (!UseGP && GAOpc != HexagonISD::CONST32)
1543 if (!
isAligned(Alignment, Const->getZExtValue()))
1548 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1549 R =
CurDAG->getTargetGlobalAddress(GA->getGlobal(),
SDLoc(Const),
1550 N.getValueType(), NewOff);
1557 case HexagonISD::CP:
1558 case HexagonISD::JT:
1559 case HexagonISD::CONST32:
1563 R =
N.getOperand(0);
1565 case HexagonISD::CONST32_GP:
1567 R =
N.getOperand(0);
1595 if (
N.getValueType() != MVT::i64)
1597 unsigned Opc =
N.getOpcode();
1603 ?
N.getOperand(0).getValueType()
1605 unsigned SW =
T.getSizeInBits();
1607 R =
N.getOperand(0);
1620 if (L->getMemoryVT().getSizeInBits() > 32)
1627 if (!S || S->getZExtValue() != 32)
1634 if (
T.getSizeInBits() == 32)
1635 R =
N.getOperand(0);
1644 EVT RT = R.getValueType();
1652 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
1653 R,
CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
1654 R,
CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
1656 SDNode *
T =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
1662bool HexagonDAGToDAGISel::keepsLowBits(
const SDValue &Val,
unsigned NumBits,
1671 if (
T.isInteger() &&
T.getSizeInBits() == NumBits) {
1682 if (
T->getVT().getSizeInBits() == NumBits) {
1692 if (
C->getZExtValue() == Mask) {
1698 if (
C->getZExtValue() == Mask) {
1710 if ((
C->getZExtValue() & Mask) == 0) {
1716 if ((
C->getZExtValue() & Mask) == 0) {
1729bool HexagonDAGToDAGISel::isAlignedMemNode(
const MemSDNode *
N)
const {
1730 return N->getAlign().value() >=
N->getMemoryVT().getStoreSize();
1733bool HexagonDAGToDAGISel::isSmallStackStore(
const StoreSDNode *
N)
const {
1734 unsigned StackSize =
MF->getFrameInfo().estimateStackSize(*
MF);
1735 switch (
N->getMemoryVT().getStoreSize()) {
1737 return StackSize <= 56;
1739 return StackSize <= 120;
1741 return StackSize <= 248;
1748bool HexagonDAGToDAGISel::isPositiveHalfWord(
const SDNode *
N)
const {
1760bool HexagonDAGToDAGISel::hasOneUse(
const SDNode *
N)
const {
1768 switch (
N->getOpcode()) {
1775 return N->getNumOperands() >= 2 &&
1783int HexagonDAGToDAGISel::getWeight(
SDNode *
N) {
1786 assert(RootWeights.count(
N) &&
"Cannot get weight of unseen root!");
1787 assert(RootWeights[
N] != -1 &&
"Cannot get weight of unvisited root!");
1788 assert(RootWeights[
N] != -2 &&
"Cannot get weight of RAWU'd root!");
1789 return RootWeights[
N];
1792int HexagonDAGToDAGISel::getHeight(
SDNode *
N) {
1795 assert(RootWeights.count(
N) && RootWeights[
N] >= 0 &&
1796 "Cannot query height of unvisited/RAUW'd node!");
1797 return RootHeights[
N];
1801struct WeightedLeaf {
1806 WeightedLeaf() =
default;
1808 WeightedLeaf(
SDValue Value,
int Weight,
int InsertionOrder) :
1809 Value(
Value), Weight(Weight), InsertionOrder(InsertionOrder) {
1810 assert(Weight >= 0 &&
"Weight must be >= 0");
1813 static bool Compare(
const WeightedLeaf &
A,
const WeightedLeaf &
B) {
1814 assert(
A.Value.getNode() &&
B.Value.getNode());
1815 return A.Weight ==
B.Weight ?
1816 (
A.InsertionOrder >
B.InsertionOrder) :
1817 (
A.Weight >
B.Weight);
1824class LeafPrioQueue {
1827 WeightedLeaf ConstElt;
1832 return (!HaveConst && Q.
empty());
1836 return Q.
size() + HaveConst;
1843 const WeightedLeaf &top() {
1849 WeightedLeaf pop() {
1854 std::pop_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1858 void push(WeightedLeaf L,
bool SeparateConst=
true) {
1871 std::push_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1877 void pushToBottom(WeightedLeaf L) {
1884 WeightedLeaf findSHL(
uint64_t MaxAmount);
1886 WeightedLeaf findMULbyConst();
1888 LeafPrioQueue(
unsigned Opcode) :
1889 HaveConst(
false), Opcode(Opcode) { }
1893WeightedLeaf LeafPrioQueue::findSHL(
uint64_t MaxAmount) {
1897 for (
int Pos = 0, End = Q.
size(); Pos != End; ++Pos) {
1898 const WeightedLeaf &
L = Q[Pos];
1905 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1912 if (
Result.Value.getNode()) {
1913 Q.
erase(&Q[ResultPos]);
1914 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1920WeightedLeaf LeafPrioQueue::findMULbyConst() {
1924 for (
int Pos = 0, End = Q.
size(); Pos != End; ++Pos) {
1925 const WeightedLeaf &
L = Q[Pos];
1932 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1939 if (
Result.Value.getNode()) {
1940 Q.
erase(&Q[ResultPos]);
1941 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1948 if (
N->getNumOperands() < 2)
1950 uint64_t MulFactor = 1ull <<
N->getConstantOperandVal(1);
1951 return CurDAG->getConstant(MulFactor, SDLoc(
N),
1952 N->getOperand(1).getValueType());
1960 unsigned MaxFactor = 0;
1961 for (
int i = 0; i < 2; ++i) {
1965 const APInt &CInt =
C->getAPIntValue();
1984 if (V.getNumOperands() < 2)
1986 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
1987 for (
int i = 0; i < 2; ++i)
1989 V.getConstantOperandVal(i) % (1ULL << Amount) == 0) {
1990 uint64_t NewConst = V.getConstantOperandVal(i) >> Amount;
1991 return (NewConst == 1);
1993 }
else if (V.getOpcode() ==
ISD::SHL) {
1994 if (V.getNumOperands() < 2 ||
1997 return (Amount == V.getConstantOperandVal(1));
2003SDValue HexagonDAGToDAGISel::factorOutPowerOf2(
SDValue V,
unsigned Power) {
2005 if (
V.getNumOperands() < 2)
2010 for (
int i=0; i < 2; ++i) {
2012 V.getConstantOperandVal(i) % ((
uint64_t)1 << Power) == 0) {
2013 uint64_t NewConst =
V.getConstantOperandVal(i) >> Power;
2017 SDLoc(V),
V.getValueType());
2024 uint64_t ShiftAmount =
V.getConstantOperandVal(1);
2025 if (ShiftAmount == Power)
2027 Ops[1] =
CurDAG->getConstant(ShiftAmount - Power,
2028 SDLoc(V),
V.getValueType());
2031 return CurDAG->getNode(
V.getOpcode(), SDLoc(V),
V.getValueType(),
Ops);
2035 return V.getOpcode() == HexagonISD::CONST32 ||
2036 V.getOpcode() == HexagonISD::CONST32_GP;
2039unsigned HexagonDAGToDAGISel::getUsesInFunction(
const Value *V) {
2040 auto [It,
Inserted] = GAUsesInFunction.try_emplace(V);
2045 const Function &CurF =
CurDAG->getMachineFunction().getFunction();
2046 for (
const User *U :
V->users()) {
2062SDValue HexagonDAGToDAGISel::balanceSubTree(
SDNode *
N,
bool TopLevel) {
2063 assert(RootWeights.count(
N) &&
"Cannot balance non-root node.");
2064 assert(RootWeights[
N] != -2 &&
"This node was RAUW'd!");
2068 if (RootWeights[
N] != -1)
2073 if (
N->getNumOperands() < 2)
2085 Weight = getWeight(balanceSubTree(Op0N).
getNode());
2088 Weight = getWeight(Op0N);
2092 Weight += getWeight(balanceSubTree(Op1N).
getNode());
2095 Weight += getWeight(Op1N);
2097 RootWeights[
N] = Weight;
2101 int Height0 = 0, Height1 = 0;
2103 RootWeights[Op0N] >= 0)
2104 Height0 = getHeight(Op0N);
2106 RootWeights[Op1N] >= 0)
2107 Height1 = getHeight(Op1N);
2109 RootHeights[
N] = std::max(Height0, Height1) + 1;
2111 LLVM_DEBUG(
dbgs() <<
"--> No need to balance root (Weight=" << Weight
2112 <<
" Height=" << RootHeights[
N] <<
"): ");
2121 unsigned NOpcode =
N->getOpcode();
2123 LeafPrioQueue Leaves(NOpcode);
2131 bool CanFactorize =
false;
2132 WeightedLeaf Mul1, Mul2;
2133 unsigned MaxPowerOf2 = 0;
2138 bool HaveTopLevelShift =
false;
2144 HaveTopLevelShift =
true;
2148 int InsertionOrder = 0;
2149 SmallDenseMap<SDValue, int> NodeHeights;
2150 bool Imbalanced =
false;
2151 int CurrentWeight = 0;
2152 while (!Worklist.
empty()) {
2158 int Weight = RootWeights[Child.
getNode()];
2160 Child = balanceSubTree(Child.
getNode());
2162 Weight = getWeight(Child.
getNode());
2163 }
else if (Weight == -2) {
2168 return balanceSubTree(
N, TopLevel);
2171 NodeHeights[Child] = 1;
2172 CurrentWeight += Weight;
2175 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&
2182 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);
2183 MaxPowerOf2 = PowerOf2;
2185 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);
2186 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);
2189 if (MaxPowerOf2 > 3)
2192 CanFactorize =
true;
2195 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2198 int Weight = getWeight(Child.
getNode());
2200 NodeHeights[Child] = getHeight(Child.
getNode());
2201 CurrentWeight += Weight;
2204 GA = WeightedLeaf(Child, Weight, InsertionOrder++);
2206 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2210 unsigned ChildOpcode = Child.
getOpcode();
2211 assert(ChildOpcode == NOpcode ||
2216 int Weight = getWeight(Child.
getNode());
2217 NodeHeights[Child] = getHeight(Child.
getNode());
2218 CurrentWeight += Weight;
2219 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2226 Op1 = getMultiplierForSHL(Child.
getNode());
2227 assert(Op1.
getNode() &&
"getMultiplierForSHL returned null");
2232 assert(!NodeHeights.
count(Child) &&
"Parent visited before children?");
2239 if (std::abs(NodeHeights[Op1] - NodeHeights[Child->
getOperand(0)]) > 1)
2242 NodeHeights[Child] = std::max(NodeHeights[Op1],
2249 <<
" weight=" << CurrentWeight
2250 <<
" imbalanced=" << Imbalanced <<
"\n");
2256 LLVM_DEBUG(
dbgs() <<
"--> Found common factor for two MUL children!\n");
2257 int Weight = Mul1.Weight + Mul2.Weight;
2258 int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;
2259 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);
2260 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);
2262 Mul1Factored, Mul2Factored);
2267 NodeHeights[
New] = Height;
2268 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));
2269 }
else if (Mul1.Value.
getNode()) {
2275 CanFactorize =
false;
2281 bool CombinedGA =
false;
2285 GlobalAddressSDNode *GANode =
2289 if (getUsesInFunction(GANode->
getGlobal()) == 1 &&
Offset->hasOneUse() &&
2292 <<
Offset->getSExtValue() <<
"): ");
2301 GA.Weight += Leaves.top().Weight;
2303 NodeHeights[GA.Value] = getHeight(GA.Value.
getNode());
2312 RootWeights[
N] = CurrentWeight;
2313 RootHeights[
N] = NodeHeights[
SDValue(
N, 0)];
2320 WeightedLeaf
SHL = Leaves.findSHL(31);
2321 if (
SHL.Value.getNode()) {
2322 int Height = std::max(NodeHeights[GA.Value], NodeHeights[
SHL.Value]) + 1;
2325 GA.Value,
SHL.Value);
2326 GA.Weight =
SHL.Weight;
2327 NodeHeights[GA.Value] = Height;
2336 if (TopLevel && !CanFactorize && Leaves.hasConst()) {
2338 Leaves.pushToBottom(Leaves.pop());
2341 const DataLayout &
DL =
CurDAG->getDataLayout();
2345 while (Leaves.size() > 1) {
2346 WeightedLeaf L0 = Leaves.pop();
2350 WeightedLeaf L1 = Leaves.findMULbyConst();
2354 assert(L0.Weight <= L1.Weight &&
"Priority queue is broken!");
2357 int V0Weight = L0.Weight;
2359 int V1Weight = L1.Weight;
2362 if ((RootWeights.count(V0.
getNode()) && RootWeights[V0.
getNode()] == -2) ||
2363 (RootWeights.count(
V1.getNode()) && RootWeights[
V1.getNode()] == -2)) {
2365 return balanceSubTree(
N, TopLevel);
2370 EVT VT =
N->getValueType(0);
2380 "Children must have been visited before re-combining them!");
2381 int Height = std::max(NodeHeights[V0], NodeHeights[
V1]) + 1;
2385 NewNode =
CurDAG->getNode(
2391 NewNode =
CurDAG->getNode(NOpcode, SDLoc(
N), VT, V0,
V1);
2393 NodeHeights[NewNode] = Height;
2395 int Weight = V0Weight + V1Weight;
2396 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));
2399 <<
",Height=" << Height <<
"):\n");
2403 assert(Leaves.size() == 1);
2404 SDValue NewRoot = Leaves.top().Value;
2407 int Height = NodeHeights[NewRoot];
2415 NewRoot =
CurDAG->getNode(
2430 RootWeights[
N] = -2;
2435 RootWeights[NewRoot.
getNode()] = Leaves.top().Weight;
2436 RootHeights[NewRoot.
getNode()] = Height;
2441void HexagonDAGToDAGISel::rebalanceAddressTrees() {
2452 if (RootWeights.count(
BasePtr.getNode()))
2455 LLVM_DEBUG(
dbgs() <<
"** Rebalancing address calculation in node: ");
2461 if (
BasePtr->getNumOperands() < 2)
2467 while (!Worklist.
empty()) {
2469 unsigned Opcode =
N->getOpcode();
2474 if (
N->getNumOperands() < 2)
2477 Worklist.
push_back(
N->getOperand(0).getNode());
2478 Worklist.
push_back(
N->getOperand(1).getNode());
2481 if (
N->hasOneUse() && Opcode ==
N->user_begin()->getOpcode())
2485 RootWeights.try_emplace(
N, -1);
2489 RootWeights[
BasePtr.getNode()] = -1;
2493 if (
N->getNumOperands() >= 3)
2494 N =
CurDAG->UpdateNodeOperands(
N,
N->getOperand(0), NewBasePtr,
2497 if (
N->getNumOperands() >= 4)
2498 N =
CurDAG->UpdateNodeOperands(
N,
N->getOperand(0),
N->getOperand(1),
2499 NewBasePtr,
N->getOperand(3));
2506 CurDAG->RemoveDeadNodes();
2507 GAUsesInFunction.clear();
2508 RootHeights.clear();
2509 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 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
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.
@ 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.
@ 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.
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.