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 =
C->getSExtValue() << ShlConst;
599 SDValue Val =
CurDAG->getTargetConstant(ValConst, dl, MVT::i32);
600 SDNode *Result =
CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
601 MVT::i32, Mul_0, Val);
618 int32_t ValConst = 1 << (ShlConst + C2->getSExtValue());
621 CurDAG->getSignedTargetConstant(-ValConst, dl, MVT::i32);
622 SDNode *Result =
CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
623 MVT::i32, Shl2_0, Val);
651 unsigned IntNo =
N->getConstantOperandVal(1);
652 if (IntNo == Intrinsic::hexagon_V6_vgathermw ||
653 IntNo == Intrinsic::hexagon_V6_vgathermw_128B ||
654 IntNo == Intrinsic::hexagon_V6_vgathermh ||
655 IntNo == Intrinsic::hexagon_V6_vgathermh_128B ||
656 IntNo == Intrinsic::hexagon_V6_vgathermhw ||
657 IntNo == Intrinsic::hexagon_V6_vgathermhw_128B ||
658 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh ||
659 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh_128B) {
663 if (IntNo == Intrinsic::hexagon_V6_vgathermwq ||
664 IntNo == Intrinsic::hexagon_V6_vgathermwq_128B ||
665 IntNo == Intrinsic::hexagon_V6_vgathermhq ||
666 IntNo == Intrinsic::hexagon_V6_vgathermhq_128B ||
667 IntNo == Intrinsic::hexagon_V6_vgathermhwq ||
668 IntNo == Intrinsic::hexagon_V6_vgathermhwq_128B) {
677 unsigned IID =
N->getConstantOperandVal(0);
680 case Intrinsic::hexagon_S2_vsplatrb:
683 case Intrinsic::hexagon_S2_vsplatrh:
686 case Intrinsic::hexagon_V6_vaddcarry:
687 case Intrinsic::hexagon_V6_vaddcarry_128B:
688 case Intrinsic::hexagon_V6_vsubcarry:
689 case Intrinsic::hexagon_V6_vsubcarry_128B:
700 if (keepsLowBits(V, Bits, U)) {
702 N->getOperand(0), U);
704 SelectCode(R.getNode());
712 MVT ResTy =
N->getValueType(0).getSimpleVT();
713 unsigned Idx =
N->getConstantOperandVal(1);
720 assert(Idx == 0 || Idx == ResLen);
722 unsigned SubReg = Idx == 0 ? Hexagon::isub_lo : Hexagon::isub_hi;
734 APInt A = CN->getValueAPF().bitcastToAPInt();
735 if (
N->getValueType(0) == MVT::f32) {
736 SDValue V =
CurDAG->getTargetConstant(
A.getZExtValue(), dl, MVT::i32);
740 if (
N->getValueType(0) == MVT::f64) {
741 SDValue V =
CurDAG->getTargetConstant(
A.getZExtValue(), dl, MVT::i64);
753 if (
N->getValueType(0) == MVT::i1) {
754 assert(!(
N->getAsZExtVal() >> 1));
782 R =
CurDAG->getMachineNode(Hexagon::PS_fi,
DL, MVT::i32, FI, Zero);
785 Register AR = HMFI.getStackAlignBaseReg();
788 R =
CurDAG->getMachineNode(Hexagon::PS_fia,
DL, MVT::i32,
Ops);
796 : Hexagon::A4_subp_c;
798 { N->getOperand(0), N->getOperand(1),
804 MVT ResTy =
N->getValueType(0).getSimpleVT();
805 if (HST->isHVXVectorType(ResTy,
true))
806 return SelectHvxVAlign(
N);
812 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
814 CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
816 CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
818 SDNode *R =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
825 if (HST->useCompound()) {
826 C =
CurDAG->getMachineNode(Hexagon::S4_andi_asl_ri, dl, MVT::i32,
827 M0,
N->getOperand(2),
M1);
829 SDNode *
T =
CurDAG->getMachineNode(Hexagon::S2_asl_i_r, dl, MVT::i32,
830 N->getOperand(2),
M1);
831 C =
CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
834 SDNode *S =
CurDAG->getMachineNode(Hexagon::S2_lsr_r_p, dl, MVT::i64,
836 SDValue E =
CurDAG->getTargetExtractSubreg(Hexagon::isub_lo, dl, ResTy,
841 SDNode *Pu =
CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::v8i1,
843 SDNode *VA =
CurDAG->getMachineNode(Hexagon::S2_valignrb, dl, ResTy,
844 N->getOperand(0),
N->getOperand(1),
857 SDNode *
AA =
CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
858 N->getOperand(0), M);
867 MVT OpTy =
Op.getValueType().getSimpleVT();
869 CurDAG->getVTList(OpTy), {Op});
874 MVT ResTy =
N->getValueType(0).getSimpleVT();
882 MVT ResTy =
N->getValueType(0).getSimpleVT();
884 SDNode *
T =
CurDAG->getMachineNode(Hexagon::A4_vcmpbgtui, dl, ResTy,
885 N->getOperand(0), Zero);
891 MVT ResTy =
N->getValueType(0).getSimpleVT();
893 MVT OpTy =
N->getOperand(0).getValueType().getSimpleVT(); (void)OpTy;
897 SDNode *R =
CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
C);
898 SDNode *
T =
CurDAG->getMachineNode(Hexagon::V6_vandvrt, dl, ResTy,
905 MVT ResTy =
N->getValueType(0).getSimpleVT();
910 SDNode *R =
CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
C);
911 SDNode *
T =
CurDAG->getMachineNode(Hexagon::V6_vandqrt, dl, ResTy,
920 Ops = {
N->getOperand(0),
N->getOperand(1)};
922 VTs =
CurDAG->getVTList(MVT::f32, MVT::f32);
923 SDNode *ResScale =
CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs,
Ops);
924 SDNode *
D =
CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32,
Ops);
928 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32,
C);
930 SDNode *n =
CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32,
Ops);
931 SDNode *Err =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
934 SDNode *NewRec =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
937 SDNode *newErr =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
941 Hexagon::A2_andir, dl, MVT::f32,
SDValue(n, 0),
942 CurDAG->getTargetConstant(0x80000000, dl, MVT::i32));
944 CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(q, 0),
947 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
950 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
SDValue(n, 0),
952 SDNode *NNewQ =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
957 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
SDValue(n, 0),
959 std::array<SDValue, 4> temp1 = {
SDValue(NNewQ, 0),
SDValue(NqErr, 0),
963 CurDAG->getMachineNode(Hexagon::F2_sffma_sc, dl, MVT::f32, OpValue1);
971 Ops = {
N->getOperand(0),
N->getOperand(1)};
973 VTs =
CurDAG->getVTList(MVT::f32, MVT::f32);
974 SDNode *ResScale =
CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs,
Ops);
975 SDNode *
D =
CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32,
Ops);
979 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32,
C);
981 SDNode *n =
CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32,
Ops);
982 SDNode *Err =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
985 SDNode *NewRec =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
988 SDNode *newErr =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
993 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
996 Hexagon::F2_sfmpy, dl, MVT::f32,
SDValue(NNewRec, 0),
SDValue(n, 0));
1001 if (
N->getFlags().hasAllowReassociation())
1008 if (
N->isMachineOpcode())
1009 return N->setNodeId(-1);
1011 auto isHvxOp = [
this](
SDNode *
N) {
1012 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
1013 if (HST->isHVXVectorType(
N->getValueType(i),
true))
1017 if (HST->isHVXVectorType(
I.getValueType(),
true))
1023 if (HST->useHVXOps() && isHvxOp(
N)) {
1024 switch (
N->getOpcode()) {
1032 switch (
N->getOpcode()) {
1061 std::vector<SDValue> &OutOps) {
1064 switch (ConstraintID) {
1071 OutOps.push_back(Res);
1073 OutOps.push_back(Inp);
1077 OutOps.push_back(
CurDAG->getTargetConstant(0,
SDLoc(
Op), MVT::i32));
1086 if (!U->hasOneUse())
1088 unsigned Opc = U->getOpcode();
1111 SDNode *SYNode = SY.getNode();
1115 if (LDBasePtr == STBasePtr)
1124void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {
1125 SelectionDAG &DAG = *
CurDAG;
1127 for (
auto *
I : Nodes) {
1131 auto IsSelect0 = [](
const SDValue &
Op) ->
bool {
1138 SDValue N0 =
I->getOperand(0), N1 =
I->getOperand(1);
1139 EVT VT =
I->getValueType(0);
1140 bool SelN0 = IsSelect0(N0);
1141 SDValue SOp = SelN0 ? N0 : N1;
1142 SDValue VOp = SelN0 ? N1 : N0;
1168void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {
1169 SelectionDAG &DAG = *
CurDAG;
1171 for (
auto *
I : Nodes) {
1172 if (
I->getOpcode() != ISD::STORE)
1203 if (EV % (1 << CV) != 0)
1205 unsigned DV = EV / (1 << CV);
1208 SDLoc
DL = SDLoc(
I);
1232void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {
1233 SelectionDAG &DAG = *
CurDAG;
1235 for (SDNode *
N : Nodes) {
1236 unsigned Opc =
N->getOpcode();
1237 if (
Opc != ISD::LOAD &&
Opc != ISD::STORE)
1239 SDValue Addr =
Opc == ISD::LOAD ?
N->getOperand(1) :
N->getOperand(2);
1273 if (TZ +
M1 + LZ != 32)
1297void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {
1298 SelectionDAG &DAG = *
CurDAG;
1300 for (SDNode *
N : Nodes) {
1301 unsigned Opc =
N->getOpcode();
1308 for (SDUse &Use :
N->uses()) {
1309 SDNode *
U =
Use.getUser();
1310 if (
U->getNumValues() != 1)
1312 EVT UVT =
U->getValueType(0);
1322 unsigned I1N =
Use.getOperandNo();
1324 for (
unsigned i = 0, n =
U->getNumOperands(); i != n; ++i)
1325 Ops[i] =
U->getOperand(i);
1326 EVT BVT =
Ops[I1N].getValueType();
1334 unsigned UseOpc =
U->getMachineOpcode();
1340 unsigned UseOpc =
U->getOpcode();
1362 auto getNodes = [
this]() -> std::vector<SDNode *> {
1363 std::vector<SDNode *>
T;
1364 T.reserve(
CurDAG->allnodes_size());
1370 if (HST->useHVXOps())
1371 PreprocessHvxISelDAG();
1375 ppSimplifyOrSelect0(getNodes());
1383 ppAddrReorderAddShl(getNodes());
1398 ppAddrRewriteAndSrl(getNodes());
1402 ppHoistZextI1(getNodes());
1405 dbgs() <<
"Preprocessed (Hexagon) selection DAG:";
1410 rebalanceAddressTrees();
1413 dbgs() <<
"Address tree balanced selection DAG:";
1422 if (!HFI.needsAligna(*
MF))
1431 auto &HRI = *HST.getRegisterInfo();
1433 for (
const MCPhysReg *R = HRI.getCalleeSavedRegs(
MF); *R; ++R) {
1439 assert(AP.
isValid() &&
"Couldn't reserve stack align register");
1445void HexagonDAGToDAGISel::updateAligna() {
1447 if (!HFI.needsAligna(*
MF))
1449 auto *AlignaI =
const_cast<MachineInstr*
>(HFI.getAlignaInstr(*
MF));
1450 assert(AlignaI !=
nullptr);
1452 if (AlignaI->getOperand(1).getImm() < MaxA)
1453 AlignaI->getOperand(1).setImm(MaxA);
1460 auto &HFI = *HST->getFrameLowering();
1465 R =
CurDAG->getTargetFrameIndex(FX, MVT::i32);
1495 EVT T =
N.getValueType();
1499 R =
CurDAG->getTargetConstant(V,
SDLoc(
N),
N.getValueType());
1505 switch (
N.getOpcode()) {
1507 if (
N.getValueType() != MVT::i32)
1512 R =
CurDAG->getTargetConstant(V,
SDLoc(
N),
N.getValueType());
1518 if (Alignment >
Align(8))
1520 R =
N.getOperand(0);
1524 if (Alignment >
Align(1))
1530 if (Alignment >
Align(4) ||
1545 bool UseGP,
Align Alignment) {
1546 switch (
N.getOpcode()) {
1556 if (!
isAligned(Alignment, Const->getZExtValue()))
1562 R =
CurDAG->getTargetGlobalAddress(GA->getGlobal(),
SDLoc(Const),
1563 N.getValueType(), NewOff);
1576 R =
N.getOperand(0);
1580 R =
N.getOperand(0);
1608 if (
N.getValueType() != MVT::i64)
1610 unsigned Opc =
N.getOpcode();
1616 ?
N.getOperand(0).getValueType()
1618 unsigned SW =
T.getSizeInBits();
1620 R =
N.getOperand(0);
1633 if (L->getMemoryVT().getSizeInBits() > 32)
1640 if (!S || S->getZExtValue() != 32)
1647 if (
T.getSizeInBits() == 32)
1648 R =
N.getOperand(0);
1657 EVT RT = R.getValueType();
1665 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
1666 R,
CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
1667 R,
CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
1669 SDNode *
T =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
1675bool HexagonDAGToDAGISel::keepsLowBits(
const SDValue &Val,
unsigned NumBits,
1684 if (
T.isInteger() &&
T.getSizeInBits() == NumBits) {
1695 if (
T->getVT().getSizeInBits() == NumBits) {
1703 uint64_t
Mask = (1ULL << NumBits) - 1;
1705 if (
C->getZExtValue() == Mask) {
1711 if (
C->getZExtValue() == Mask) {
1721 uint64_t
Mask = (1ULL << NumBits) - 1;
1723 if ((
C->getZExtValue() & Mask) == 0) {
1729 if ((
C->getZExtValue() & Mask) == 0) {
1742bool HexagonDAGToDAGISel::isAlignedMemNode(
const MemSDNode *
N)
const {
1743 return N->getAlign().value() >=
N->getMemoryVT().getStoreSize();
1746bool HexagonDAGToDAGISel::isSmallStackStore(
const StoreSDNode *
N)
const {
1747 unsigned StackSize =
MF->getFrameInfo().estimateStackSize(*
MF);
1748 switch (
N->getMemoryVT().getStoreSize()) {
1750 return StackSize <= 56;
1752 return StackSize <= 120;
1754 return StackSize <= 248;
1761bool HexagonDAGToDAGISel::isPositiveHalfWord(
const SDNode *
N)
const {
1773bool HexagonDAGToDAGISel::hasOneUse(
const SDNode *
N)
const {
1781 switch (
N->getOpcode()) {
1795int HexagonDAGToDAGISel::getWeight(
SDNode *
N) {
1798 assert(RootWeights.count(
N) &&
"Cannot get weight of unseen root!");
1799 assert(RootWeights[
N] != -1 &&
"Cannot get weight of unvisited root!");
1800 assert(RootWeights[
N] != -2 &&
"Cannot get weight of RAWU'd root!");
1801 return RootWeights[
N];
1804int HexagonDAGToDAGISel::getHeight(
SDNode *
N) {
1807 assert(RootWeights.count(
N) && RootWeights[
N] >= 0 &&
1808 "Cannot query height of unvisited/RAUW'd node!");
1809 return RootHeights[
N];
1813struct WeightedLeaf {
1818 WeightedLeaf() =
default;
1820 WeightedLeaf(
SDValue Value,
int Weight,
int InsertionOrder) :
1821 Value(
Value), Weight(Weight), InsertionOrder(InsertionOrder) {
1822 assert(Weight >= 0 &&
"Weight must be >= 0");
1825 static bool Compare(
const WeightedLeaf &
A,
const WeightedLeaf &
B) {
1826 assert(
A.Value.getNode() &&
B.Value.getNode());
1827 return A.Weight ==
B.Weight ?
1828 (
A.InsertionOrder >
B.InsertionOrder) :
1829 (
A.Weight >
B.Weight);
1836class LeafPrioQueue {
1839 WeightedLeaf ConstElt;
1844 return (!HaveConst && Q.
empty());
1848 return Q.
size() + HaveConst;
1855 const WeightedLeaf &top() {
1861 WeightedLeaf pop() {
1866 std::pop_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1870 void push(WeightedLeaf L,
bool SeparateConst=
true) {
1883 std::push_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1889 void pushToBottom(WeightedLeaf L) {
1896 WeightedLeaf findSHL(uint64_t MaxAmount);
1898 WeightedLeaf findMULbyConst();
1900 LeafPrioQueue(
unsigned Opcode) :
1901 HaveConst(
false), Opcode(Opcode) { }
1905WeightedLeaf LeafPrioQueue::findSHL(uint64_t MaxAmount) {
1909 for (
int Pos = 0, End = Q.
size(); Pos != End; ++Pos) {
1910 const WeightedLeaf &
L = Q[Pos];
1917 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1924 if (
Result.Value.getNode()) {
1925 Q.
erase(&Q[ResultPos]);
1926 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1932WeightedLeaf LeafPrioQueue::findMULbyConst() {
1936 for (
int Pos = 0, End = Q.
size(); Pos != End; ++Pos) {
1937 const WeightedLeaf &
L = Q[Pos];
1944 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1951 if (
Result.Value.getNode()) {
1952 Q.
erase(&Q[ResultPos]);
1953 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1961 return CurDAG->getConstant(MulFactor, SDLoc(
N),
1962 N->getOperand(1).getValueType());
1968 unsigned MaxFactor = 0;
1969 for (
int i = 0; i < 2; ++i) {
1973 const APInt &CInt =
C->getAPIntValue();
1991 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
1992 for (
int i = 0; i < 2; ++i)
1994 V.getConstantOperandVal(i) % (1ULL << Amount) == 0) {
1995 uint64_t NewConst = V.getConstantOperandVal(i) >> Amount;
1996 return (NewConst == 1);
1998 }
else if (V.getOpcode() ==
ISD::SHL) {
1999 return (Amount == V.getConstantOperandVal(1));
2005SDValue HexagonDAGToDAGISel::factorOutPowerOf2(
SDValue V,
unsigned Power) {
2008 for (
int i=0; i < 2; ++i) {
2010 V.getConstantOperandVal(i) % ((uint64_t)1 << Power) == 0) {
2011 uint64_t NewConst =
V.getConstantOperandVal(i) >> Power;
2015 SDLoc(V),
V.getValueType());
2020 uint64_t ShiftAmount =
V.getConstantOperandVal(1);
2021 if (ShiftAmount == Power)
2023 Ops[1] =
CurDAG->getConstant(ShiftAmount - Power,
2024 SDLoc(V),
V.getValueType());
2027 return CurDAG->getNode(
V.getOpcode(), SDLoc(V),
V.getValueType(),
Ops);
2035unsigned HexagonDAGToDAGISel::getUsesInFunction(
const Value *V) {
2036 auto [It,
Inserted] = GAUsesInFunction.try_emplace(V);
2041 const Function &CurF =
CurDAG->getMachineFunction().getFunction();
2042 for (
const User *U :
V->users()) {
2058SDValue HexagonDAGToDAGISel::balanceSubTree(
SDNode *
N,
bool TopLevel) {
2059 assert(RootWeights.count(
N) &&
"Cannot balance non-root node.");
2060 assert(RootWeights[
N] != -2 &&
"This node was RAUW'd!");
2064 if (RootWeights[
N] != -1)
2078 Weight = getWeight(balanceSubTree(Op0N).
getNode());
2081 Weight = getWeight(Op0N);
2083 SDNode *Op1N =
N->getOperand(1).getNode();
2085 Weight += getWeight(balanceSubTree(Op1N).
getNode());
2088 Weight += getWeight(Op1N);
2090 RootWeights[
N] = Weight;
2091 RootHeights[
N] = std::max(getHeight(
N->getOperand(0).getNode()),
2092 getHeight(
N->getOperand(1).getNode())) + 1;
2094 LLVM_DEBUG(
dbgs() <<
"--> No need to balance root (Weight=" << Weight
2095 <<
" Height=" << RootHeights[
N] <<
"): ");
2104 unsigned NOpcode =
N->getOpcode();
2106 LeafPrioQueue Leaves(NOpcode);
2114 bool CanFactorize =
false;
2115 WeightedLeaf Mul1, Mul2;
2116 unsigned MaxPowerOf2 = 0;
2121 bool HaveTopLevelShift =
false;
2127 HaveTopLevelShift =
true;
2131 int InsertionOrder = 0;
2132 SmallDenseMap<SDValue, int> NodeHeights;
2133 bool Imbalanced =
false;
2134 int CurrentWeight = 0;
2135 while (!Worklist.
empty()) {
2141 int Weight = RootWeights[Child.
getNode()];
2143 Child = balanceSubTree(Child.
getNode());
2145 Weight = getWeight(Child.
getNode());
2146 }
else if (Weight == -2) {
2151 return balanceSubTree(
N, TopLevel);
2154 NodeHeights[Child] = 1;
2155 CurrentWeight += Weight;
2158 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&
2165 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);
2166 MaxPowerOf2 = PowerOf2;
2168 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);
2169 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);
2172 if (MaxPowerOf2 > 3)
2175 CanFactorize =
true;
2178 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2181 int Weight = getWeight(Child.
getNode());
2183 NodeHeights[Child] = getHeight(Child.
getNode());
2184 CurrentWeight += Weight;
2187 GA = WeightedLeaf(Child, Weight, InsertionOrder++);
2189 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2193 unsigned ChildOpcode = Child.
getOpcode();
2194 assert(ChildOpcode == NOpcode ||
2200 Op1 = getMultiplierForSHL(Child.
getNode());
2205 assert(!NodeHeights.
count(Child) &&
"Parent visited before children?");
2212 if (std::abs(NodeHeights[Op1] - NodeHeights[Child->
getOperand(0)]) > 1)
2215 NodeHeights[Child] = std::max(NodeHeights[Op1],
2222 <<
" weight=" << CurrentWeight
2223 <<
" imbalanced=" << Imbalanced <<
"\n");
2229 LLVM_DEBUG(
dbgs() <<
"--> Found common factor for two MUL children!\n");
2230 int Weight = Mul1.Weight + Mul2.Weight;
2231 int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;
2232 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);
2233 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);
2235 Mul1Factored, Mul2Factored);
2240 NodeHeights[
New] = Height;
2241 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));
2242 }
else if (Mul1.Value.
getNode()) {
2248 CanFactorize =
false;
2254 bool CombinedGA =
false;
2257 GlobalAddressSDNode *GANode =
2261 if (getUsesInFunction(GANode->
getGlobal()) == 1 &&
Offset->hasOneUse() &&
2264 <<
Offset->getSExtValue() <<
"): ");
2273 GA.Weight += Leaves.top().Weight;
2275 NodeHeights[GA.Value] = getHeight(GA.Value.
getNode());
2284 RootWeights[
N] = CurrentWeight;
2285 RootHeights[
N] = NodeHeights[
SDValue(
N, 0)];
2292 WeightedLeaf
SHL = Leaves.findSHL(31);
2293 if (
SHL.Value.getNode()) {
2294 int Height = std::max(NodeHeights[GA.Value], NodeHeights[
SHL.Value]) + 1;
2297 GA.Value,
SHL.Value);
2298 GA.Weight =
SHL.Weight;
2299 NodeHeights[GA.Value] = Height;
2308 if (TopLevel && !CanFactorize && Leaves.hasConst()) {
2310 Leaves.pushToBottom(Leaves.pop());
2313 const DataLayout &
DL =
CurDAG->getDataLayout();
2317 while (Leaves.size() > 1) {
2318 WeightedLeaf L0 = Leaves.pop();
2322 WeightedLeaf L1 = Leaves.findMULbyConst();
2326 assert(L0.Weight <= L1.Weight &&
"Priority queue is broken!");
2329 int V0Weight = L0.Weight;
2331 int V1Weight = L1.Weight;
2334 if ((RootWeights.count(V0.
getNode()) && RootWeights[V0.
getNode()] == -2) ||
2335 (RootWeights.count(V1.
getNode()) && RootWeights[V1.
getNode()] == -2)) {
2337 return balanceSubTree(
N, TopLevel);
2342 EVT VT =
N->getValueType(0);
2352 "Children must have been visited before re-combining them!");
2353 int Height = std::max(NodeHeights[V0], NodeHeights[V1]) + 1;
2357 NewNode =
CurDAG->getNode(
2363 NewNode =
CurDAG->getNode(NOpcode, SDLoc(
N), VT, V0, V1);
2365 NodeHeights[NewNode] = Height;
2367 int Weight = V0Weight + V1Weight;
2368 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));
2371 <<
",Height=" << Height <<
"):\n");
2375 assert(Leaves.size() == 1);
2376 SDValue NewRoot = Leaves.top().Value;
2379 int Height = NodeHeights[NewRoot];
2387 NewRoot =
CurDAG->getNode(
2402 RootWeights[
N] = -2;
2407 RootWeights[NewRoot.
getNode()] = Leaves.top().Weight;
2408 RootHeights[NewRoot.
getNode()] = Height;
2413void HexagonDAGToDAGISel::rebalanceAddressTrees() {
2416 if (
N->getOpcode() != ISD::LOAD &&
N->getOpcode() != ISD::STORE)
2424 if (RootWeights.count(
BasePtr.getNode()))
2427 LLVM_DEBUG(
dbgs() <<
"** Rebalancing address calculation in node: ");
2436 while (!Worklist.
empty()) {
2438 unsigned Opcode =
N->getOpcode();
2443 Worklist.
push_back(
N->getOperand(0).getNode());
2444 Worklist.
push_back(
N->getOperand(1).getNode());
2447 if (
N->hasOneUse() && Opcode ==
N->user_begin()->getOpcode())
2451 RootWeights.try_emplace(
N, -1);
2455 RootWeights[
BasePtr.getNode()] = -1;
2458 if (
N->getOpcode() == ISD::LOAD)
2459 N =
CurDAG->UpdateNodeOperands(
N,
N->getOperand(0),
2460 NewBasePtr,
N->getOperand(2));
2462 N =
CurDAG->UpdateNodeOperands(
N,
N->getOperand(0),
N->getOperand(1),
2463 NewBasePtr,
N->getOperand(3));
2469 CurDAG->RemoveDeadNodes();
2470 GAUsesInFunction.clear();
2471 RootHeights.clear();
2472 RootWeights.clear();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis false
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool willShiftRightEliminate(SDValue V, unsigned Amount)
static cl::opt< bool > RebalanceOnlyImbalancedTrees("rebalance-only-imbal", cl::Hidden, cl::init(false), cl::desc("Rebalance address tree only if it is imbalanced"))
static unsigned getPowerOf2Factor(SDValue Val)
static cl::opt< bool > CheckSingleUse("hexagon-isel-su", cl::Hidden, cl::init(true), cl::desc("Enable checking of SDNode's single-use status"))
static cl::opt< bool > EnableAddressRebalancing("isel-rebalance-addr", cl::Hidden, cl::init(true), cl::desc("Rebalance address calculation trees to improve " "instruction selection"))
static bool isMemOPCandidate(SDNode *I, SDNode *U)
static bool isTargetConstant(const SDValue &V)
static bool isOpcodeHandled(const SDNode *N)
static cl::opt< bool > RebalanceOnlyForOptimizations("rebalance-only-opt", cl::Hidden, cl::init(false), cl::desc("Rebalance address tree only if this allows optimizations"))
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
Class for arbitrary precision integers.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned logBase2() const
bool getBoolValue() const
Convert APInt to a boolean value.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
FunctionPass class - This class is used to implement most global optimizations.
int64_t getOffset() const
const GlobalValue * getGlobal() const
This class is used to form a handle around another node that is persistent and is updated across invo...
const SDValue & getValue() const
HexagonDAGToDAGISelLegacy(HexagonTargetMachine &tm, CodeGenOptLevel OptLevel)
void SelectAddSubCarry(SDNode *N)
void SelectConstant(SDNode *N)
void SelectIntrinsicWOChain(SDNode *N)
void Select(SDNode *N) override
Main hook for targets to transform nodes into machine nodes.
bool SelectNewCircIntrinsic(SDNode *IntN)
Generate a machine instruction node for the new circular buffer intrinsics.
bool tryLoadOfLoadIntrinsic(LoadSDNode *N)
void SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl)
void SelectExtractSubvector(SDNode *N)
void SelectVAlign(SDNode *N)
MachineSDNode * LoadInstrForLoadIntrinsic(SDNode *IntN)
bool SelectAnyImm2(SDValue &N, SDValue &R)
bool SelectAnyImm(SDValue &N, SDValue &R)
void SelectV65GatherPred(SDNode *N)
bool SelectAnyImm0(SDValue &N, SDValue &R)
void SelectSHL(SDNode *N)
void SelectIntrinsicWChain(SDNode *N)
void SelectV2Q(SDNode *N)
bool SelectAnyImm1(SDValue &N, SDValue &R)
void SelectConstantFP(SDNode *N)
bool DetectUseSxtw(SDValue &N, SDValue &R)
bool SelectBrevLdIntrinsic(SDNode *IntN)
void emitFunctionEntryCode() override
bool SelectAddrFI(SDValue &N, SDValue &R)
SDNode * StoreInstrForLoadIntrinsic(MachineSDNode *LoadN, SDNode *IntN)
bool SelectAddrGP(SDValue &N, SDValue &R)
bool SelectAnyImmediate(SDValue &N, SDValue &R, Align Alignment)
bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP, Align Alignment)
void SelectFrameIndex(SDNode *N)
bool SelectAnyImm3(SDValue &N, SDValue &R)
void SelectFDiv(SDNode *N)
void SelectStore(SDNode *N)
void SelectLoad(SDNode *N)
HexagonDAGToDAGISel()=delete
bool SelectAnyInt(SDValue &N, SDValue &R)
bool SelectAddrGA(SDValue &N, SDValue &R)
void PreprocessISelDAG() override
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
void SelectTypecast(SDNode *N)
void SelectD2P(SDNode *N)
void SelectVAlignAddr(SDNode *N)
void SelectP2D(SDNode *N)
bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps) override
SelectInlineAsmMemoryOperand - Implement addressing mode selection for inline asm expressions.
void SelectV65Gather(SDNode *N)
void SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl)
void SelectHVXDualOutput(SDNode *N)
void SelectQ2V(SDNode *N)
Hexagon target-specific information for each MachineFunction.
const HexagonFrameLowering * getFrameLowering() const override
This class is used to represent ISD::LOAD nodes.
unsigned getVectorNumElements() const
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
MVT getVectorElementType() const
static MVT getIntegerVT(unsigned BitWidth)
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
A description of a memory reference used in the backend.
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
LLVM_ABI void dump() const
Dump this node, for debugging.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
SelectionDAGISelLegacy(char &ID, std::unique_ptr< SelectionDAGISel > S)
const TargetLowering * TLI
void ReplaceUses(SDValue F, SDValue T)
ReplaceUses - replace all uses of the old node F with the use of the new node T.
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
const TargetLowering * getTargetLowering() const
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ SIGN_EXTEND
Conversion operators.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
initializer< Ty > init(const Ty &Val)
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned M1(unsigned Val)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionPass * createHexagonISelDag(HexagonTargetMachine &TM, CodeGenOptLevel OptLevel)
createHexagonISelDag - This pass converts a legalized DAG into a Hexagon-specific DAG,...
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
@ Default
The result values are uniform if and only if all operands are uniform.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isVector() const
Return true if this is a vector value type.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isInteger() const
Return true if this is an integer or a vector integer type.
This class contains a discriminated union of information about pointers in memory operands,...
This represents a list of ValueType's that has been intern'd by a SelectionDAG.