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) {
679 unsigned IID =
N->getConstantOperandVal(0);
682 case Intrinsic::hexagon_S2_vsplatrb:
685 case Intrinsic::hexagon_S2_vsplatrh:
688 case Intrinsic::hexagon_V6_vaddcarry:
689 case Intrinsic::hexagon_V6_vaddcarry_128B:
690 case Intrinsic::hexagon_V6_vsubcarry:
691 case Intrinsic::hexagon_V6_vsubcarry_128B:
702 if (keepsLowBits(V, Bits, U)) {
704 N->getOperand(0), U);
706 SelectCode(R.getNode());
714 MVT ResTy =
N->getValueType(0).getSimpleVT();
715 unsigned Idx =
N->getConstantOperandVal(1);
722 assert(Idx == 0 || Idx == ResLen);
724 unsigned SubReg = Idx == 0 ? Hexagon::isub_lo : Hexagon::isub_hi;
736 APInt A = CN->getValueAPF().bitcastToAPInt();
737 if (
N->getValueType(0) == MVT::f32) {
738 SDValue V =
CurDAG->getTargetConstant(
A.getZExtValue(), dl, MVT::i32);
742 if (
N->getValueType(0) == MVT::f64) {
743 SDValue V =
CurDAG->getTargetConstant(
A.getZExtValue(), dl, MVT::i64);
755 if (
N->getValueType(0) == MVT::i1) {
756 assert(!(
N->getAsZExtVal() >> 1));
784 R =
CurDAG->getMachineNode(Hexagon::PS_fi,
DL, MVT::i32, FI, Zero);
787 Register AR = HMFI.getStackAlignBaseReg();
790 R =
CurDAG->getMachineNode(Hexagon::PS_fia,
DL, MVT::i32,
Ops);
797 unsigned OpcCarry =
N->getOpcode() == HexagonISD::ADDC ? Hexagon::A4_addp_c
798 : Hexagon::A4_subp_c;
800 { N->getOperand(0), N->getOperand(1),
806 MVT ResTy =
N->getValueType(0).getSimpleVT();
807 if (HST->isHVXVectorType(ResTy,
true))
808 return SelectHvxVAlign(
N);
814 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
816 CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
818 CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
820 SDNode *R =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
827 if (HST->useCompound()) {
828 C =
CurDAG->getMachineNode(Hexagon::S4_andi_asl_ri, dl, MVT::i32,
829 M0,
N->getOperand(2),
M1);
831 SDNode *
T =
CurDAG->getMachineNode(Hexagon::S2_asl_i_r, dl, MVT::i32,
832 N->getOperand(2),
M1);
833 C =
CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
836 SDNode *S =
CurDAG->getMachineNode(Hexagon::S2_lsr_r_p, dl, MVT::i64,
838 SDValue E =
CurDAG->getTargetExtractSubreg(Hexagon::isub_lo, dl, ResTy,
843 SDNode *Pu =
CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::v8i1,
845 SDNode *VA =
CurDAG->getMachineNode(Hexagon::S2_valignrb, dl, ResTy,
846 N->getOperand(0),
N->getOperand(1),
859 SDNode *
AA =
CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
860 N->getOperand(0), M);
869 MVT OpTy =
Op.getValueType().getSimpleVT();
871 CurDAG->getVTList(OpTy), {Op});
876 MVT ResTy =
N->getValueType(0).getSimpleVT();
884 MVT ResTy =
N->getValueType(0).getSimpleVT();
886 SDNode *
T =
CurDAG->getMachineNode(Hexagon::A4_vcmpbgtui, dl, ResTy,
887 N->getOperand(0), Zero);
893 MVT ResTy =
N->getValueType(0).getSimpleVT();
895 MVT OpTy =
N->getOperand(0).getValueType().getSimpleVT(); (void)OpTy;
899 SDNode *R =
CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
C);
900 SDNode *
T =
CurDAG->getMachineNode(Hexagon::V6_vandvrt, dl, ResTy,
907 MVT ResTy =
N->getValueType(0).getSimpleVT();
912 SDNode *R =
CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
C);
913 SDNode *
T =
CurDAG->getMachineNode(Hexagon::V6_vandqrt, dl, ResTy,
922 Ops = {
N->getOperand(0),
N->getOperand(1)};
924 VTs =
CurDAG->getVTList(MVT::f32, MVT::f32);
925 SDNode *ResScale =
CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs,
Ops);
926 SDNode *
D =
CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32,
Ops);
930 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32,
C);
932 SDNode *n =
CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32,
Ops);
933 SDNode *Err =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
936 SDNode *NewRec =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
939 SDNode *newErr =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
943 Hexagon::A2_andir, dl, MVT::f32,
SDValue(n, 0),
944 CurDAG->getTargetConstant(0x80000000, dl, MVT::i32));
946 CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(q, 0),
949 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
952 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
SDValue(n, 0),
954 SDNode *NNewQ =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
959 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
SDValue(n, 0),
961 std::array<SDValue, 4> temp1 = {
SDValue(NNewQ, 0),
SDValue(NqErr, 0),
965 CurDAG->getMachineNode(Hexagon::F2_sffma_sc, dl, MVT::f32, OpValue1);
973 Ops = {
N->getOperand(0),
N->getOperand(1)};
975 VTs =
CurDAG->getVTList(MVT::f32, MVT::f32);
976 SDNode *ResScale =
CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs,
Ops);
977 SDNode *
D =
CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32,
Ops);
981 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32,
C);
983 SDNode *n =
CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32,
Ops);
984 SDNode *Err =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
987 SDNode *NewRec =
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
990 SDNode *newErr =
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
995 Hexagon::F2_sffma_lib, dl, MVT::f32,
SDValue(NewRec, 0),
998 Hexagon::F2_sfmpy, dl, MVT::f32,
SDValue(NNewRec, 0),
SDValue(n, 0));
1003 if (
N->getFlags().hasAllowReassociation())
1010 if (
N->isMachineOpcode())
1011 return N->setNodeId(-1);
1013 auto isHvxOp = [
this](
SDNode *
N) {
1014 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
1015 if (HST->isHVXVectorType(
N->getValueType(i),
true))
1019 if (HST->isHVXVectorType(
I.getValueType(),
true))
1025 if (HST->useHVXOps() && isHvxOp(
N)) {
1026 switch (
N->getOpcode()) {
1034 switch (
N->getOpcode()) {
1045 case HexagonISD::ADDC:
1063 std::vector<SDValue> &OutOps) {
1066 switch (ConstraintID) {
1073 OutOps.push_back(Res);
1075 OutOps.push_back(Inp);
1079 OutOps.push_back(
CurDAG->getTargetConstant(0,
SDLoc(
Op), MVT::i32));
1088 if (!U->hasOneUse())
1090 unsigned Opc = U->getOpcode();
1113 SDNode *SYNode = SY.getNode();
1117 if (LDBasePtr == STBasePtr)
1126void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {
1127 SelectionDAG &DAG = *
CurDAG;
1129 for (
auto *
I : Nodes) {
1133 auto IsSelect0 = [](
const SDValue &
Op) ->
bool {
1140 SDValue N0 =
I->getOperand(0), N1 =
I->getOperand(1);
1141 EVT VT =
I->getValueType(0);
1142 bool SelN0 = IsSelect0(N0);
1143 SDValue SOp = SelN0 ? N0 : N1;
1144 SDValue VOp = SelN0 ? N1 : N0;
1170void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {
1171 SelectionDAG &DAG = *
CurDAG;
1173 for (
auto *
I : Nodes) {
1205 if (EV % (1 << CV) != 0)
1207 unsigned DV = EV / (1 << CV);
1210 SDLoc
DL = SDLoc(
I);
1234void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {
1235 SelectionDAG &DAG = *
CurDAG;
1237 for (SDNode *
N : Nodes) {
1238 unsigned Opc =
N->getOpcode();
1275 if (TZ +
M1 + LZ != 32)
1299void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {
1300 SelectionDAG &DAG = *
CurDAG;
1302 for (SDNode *
N : Nodes) {
1303 unsigned Opc =
N->getOpcode();
1310 for (SDUse &Use :
N->uses()) {
1311 SDNode *
U =
Use.getUser();
1312 if (
U->getNumValues() != 1)
1314 EVT UVT =
U->getValueType(0);
1324 unsigned I1N =
Use.getOperandNo();
1326 for (
unsigned i = 0, n =
U->getNumOperands(); i != n; ++i)
1327 Ops[i] =
U->getOperand(i);
1328 EVT BVT =
Ops[I1N].getValueType();
1336 unsigned UseOpc =
U->getMachineOpcode();
1342 unsigned UseOpc =
U->getOpcode();
1364 auto getNodes = [
this]() -> std::vector<SDNode *> {
1365 std::vector<SDNode *>
T;
1366 T.reserve(
CurDAG->allnodes_size());
1372 if (HST->useHVXOps())
1373 PreprocessHvxISelDAG();
1377 ppSimplifyOrSelect0(getNodes());
1385 ppAddrReorderAddShl(getNodes());
1400 ppAddrRewriteAndSrl(getNodes());
1404 ppHoistZextI1(getNodes());
1407 dbgs() <<
"Preprocessed (Hexagon) selection DAG:";
1412 rebalanceAddressTrees();
1415 dbgs() <<
"Address tree balanced selection DAG:";
1424 if (!HFI.needsAligna(*
MF))
1433 auto &HRI = *HST.getRegisterInfo();
1435 for (
const MCPhysReg *R = HRI.getCalleeSavedRegs(
MF); *R; ++R) {
1441 assert(AP.
isValid() &&
"Couldn't reserve stack align register");
1447void HexagonDAGToDAGISel::updateAligna() {
1449 if (!HFI.needsAligna(*
MF))
1451 auto *AlignaI =
const_cast<MachineInstr*
>(HFI.getAlignaInstr(*
MF));
1452 assert(AlignaI !=
nullptr);
1454 if (AlignaI->getOperand(1).getImm() < MaxA)
1455 AlignaI->getOperand(1).setImm(MaxA);
1462 auto &HFI = *HST->getFrameLowering();
1467 R =
CurDAG->getTargetFrameIndex(FX, MVT::i32);
1497 EVT T =
N.getValueType();
1501 R =
CurDAG->getTargetConstant(V,
SDLoc(
N),
N.getValueType());
1507 switch (
N.getOpcode()) {
1509 if (
N.getValueType() != MVT::i32)
1514 R =
CurDAG->getTargetConstant(V,
SDLoc(
N),
N.getValueType());
1517 case HexagonISD::JT:
1518 case HexagonISD::CP:
1520 if (Alignment >
Align(8))
1522 R =
N.getOperand(0);
1526 if (Alignment >
Align(1))
1532 if (Alignment >
Align(4) ||
1547 bool UseGP,
Align Alignment) {
1548 switch (
N.getOpcode()) {
1553 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1555 if (!UseGP && GAOpc != HexagonISD::CONST32)
1558 if (!
isAligned(Alignment, Const->getZExtValue()))
1564 R =
CurDAG->getTargetGlobalAddress(GA->getGlobal(),
SDLoc(Const),
1565 N.getValueType(), NewOff);
1572 case HexagonISD::CP:
1573 case HexagonISD::JT:
1574 case HexagonISD::CONST32:
1578 R =
N.getOperand(0);
1580 case HexagonISD::CONST32_GP:
1582 R =
N.getOperand(0);
1610 if (
N.getValueType() != MVT::i64)
1612 unsigned Opc =
N.getOpcode();
1618 ?
N.getOperand(0).getValueType()
1620 unsigned SW =
T.getSizeInBits();
1622 R =
N.getOperand(0);
1635 if (L->getMemoryVT().getSizeInBits() > 32)
1642 if (!S || S->getZExtValue() != 32)
1649 if (
T.getSizeInBits() == 32)
1650 R =
N.getOperand(0);
1659 EVT RT = R.getValueType();
1667 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
1668 R,
CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
1669 R,
CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
1671 SDNode *
T =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
1677bool HexagonDAGToDAGISel::keepsLowBits(
const SDValue &Val,
unsigned NumBits,
1686 if (
T.isInteger() &&
T.getSizeInBits() == NumBits) {
1697 if (
T->getVT().getSizeInBits() == NumBits) {
1705 uint64_t
Mask = (1ULL << NumBits) - 1;
1707 if (
C->getZExtValue() == Mask) {
1713 if (
C->getZExtValue() == Mask) {
1723 uint64_t
Mask = (1ULL << NumBits) - 1;
1725 if ((
C->getZExtValue() & Mask) == 0) {
1731 if ((
C->getZExtValue() & Mask) == 0) {
1744bool HexagonDAGToDAGISel::isAlignedMemNode(
const MemSDNode *
N)
const {
1745 return N->getAlign().value() >=
N->getMemoryVT().getStoreSize();
1748bool HexagonDAGToDAGISel::isSmallStackStore(
const StoreSDNode *
N)
const {
1749 unsigned StackSize =
MF->getFrameInfo().estimateStackSize(*
MF);
1750 switch (
N->getMemoryVT().getStoreSize()) {
1752 return StackSize <= 56;
1754 return StackSize <= 120;
1756 return StackSize <= 248;
1763bool HexagonDAGToDAGISel::isPositiveHalfWord(
const SDNode *
N)
const {
1775bool HexagonDAGToDAGISel::hasOneUse(
const SDNode *
N)
const {
1783 switch (
N->getOpcode()) {
1790 return N->getNumOperands() >= 2 &&
1798int HexagonDAGToDAGISel::getWeight(
SDNode *
N) {
1801 assert(RootWeights.count(
N) &&
"Cannot get weight of unseen root!");
1802 assert(RootWeights[
N] != -1 &&
"Cannot get weight of unvisited root!");
1803 assert(RootWeights[
N] != -2 &&
"Cannot get weight of RAWU'd root!");
1804 return RootWeights[
N];
1807int HexagonDAGToDAGISel::getHeight(
SDNode *
N) {
1810 assert(RootWeights.count(
N) && RootWeights[
N] >= 0 &&
1811 "Cannot query height of unvisited/RAUW'd node!");
1812 return RootHeights[
N];
1816struct WeightedLeaf {
1821 WeightedLeaf() =
default;
1823 WeightedLeaf(
SDValue Value,
int Weight,
int InsertionOrder) :
1824 Value(
Value), Weight(Weight), InsertionOrder(InsertionOrder) {
1825 assert(Weight >= 0 &&
"Weight must be >= 0");
1828 static bool Compare(
const WeightedLeaf &
A,
const WeightedLeaf &
B) {
1829 assert(
A.Value.getNode() &&
B.Value.getNode());
1830 return A.Weight ==
B.Weight ?
1831 (
A.InsertionOrder >
B.InsertionOrder) :
1832 (
A.Weight >
B.Weight);
1839class LeafPrioQueue {
1842 WeightedLeaf ConstElt;
1847 return (!HaveConst && Q.
empty());
1851 return Q.
size() + HaveConst;
1858 const WeightedLeaf &top() {
1864 WeightedLeaf pop() {
1869 std::pop_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1873 void push(WeightedLeaf L,
bool SeparateConst=
true) {
1886 std::push_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1892 void pushToBottom(WeightedLeaf L) {
1899 WeightedLeaf findSHL(uint64_t MaxAmount);
1901 WeightedLeaf findMULbyConst();
1903 LeafPrioQueue(
unsigned Opcode) :
1904 HaveConst(
false), Opcode(Opcode) { }
1908WeightedLeaf LeafPrioQueue::findSHL(uint64_t MaxAmount) {
1912 for (
int Pos = 0, End = Q.
size(); Pos != End; ++Pos) {
1913 const WeightedLeaf &
L = Q[Pos];
1920 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1927 if (
Result.Value.getNode()) {
1928 Q.
erase(&Q[ResultPos]);
1929 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1935WeightedLeaf LeafPrioQueue::findMULbyConst() {
1939 for (
int Pos = 0, End = Q.
size(); Pos != End; ++Pos) {
1940 const WeightedLeaf &
L = Q[Pos];
1947 (
Result.Weight ==
L.Weight &&
Result.InsertionOrder >
L.InsertionOrder))
1954 if (
Result.Value.getNode()) {
1955 Q.
erase(&Q[ResultPos]);
1956 std::make_heap(Q.
begin(), Q.
end(), WeightedLeaf::Compare);
1963 if (
N->getNumOperands() < 2)
1965 uint64_t MulFactor = 1ull <<
N->getConstantOperandVal(1);
1966 return CurDAG->getConstant(MulFactor, SDLoc(
N),
1967 N->getOperand(1).getValueType());
1975 unsigned MaxFactor = 0;
1976 for (
int i = 0; i < 2; ++i) {
1980 const APInt &CInt =
C->getAPIntValue();
1999 if (V.getNumOperands() < 2)
2001 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
2002 for (
int i = 0; i < 2; ++i)
2004 V.getConstantOperandVal(i) % (1ULL << Amount) == 0) {
2005 uint64_t NewConst = V.getConstantOperandVal(i) >> Amount;
2006 return (NewConst == 1);
2008 }
else if (V.getOpcode() ==
ISD::SHL) {
2009 if (V.getNumOperands() < 2 ||
2012 return (Amount == V.getConstantOperandVal(1));
2018SDValue HexagonDAGToDAGISel::factorOutPowerOf2(
SDValue V,
unsigned Power) {
2020 if (
V.getNumOperands() < 2)
2025 for (
int i=0; i < 2; ++i) {
2027 V.getConstantOperandVal(i) % ((uint64_t)1 << Power) == 0) {
2028 uint64_t NewConst =
V.getConstantOperandVal(i) >> Power;
2032 SDLoc(V),
V.getValueType());
2039 uint64_t ShiftAmount =
V.getConstantOperandVal(1);
2040 if (ShiftAmount == Power)
2042 Ops[1] =
CurDAG->getConstant(ShiftAmount - Power,
2043 SDLoc(V),
V.getValueType());
2046 return CurDAG->getNode(
V.getOpcode(), SDLoc(V),
V.getValueType(),
Ops);
2050 return V.getOpcode() == HexagonISD::CONST32 ||
2051 V.getOpcode() == HexagonISD::CONST32_GP;
2054unsigned HexagonDAGToDAGISel::getUsesInFunction(
const Value *V) {
2055 auto [It,
Inserted] = GAUsesInFunction.try_emplace(V);
2060 const Function &CurF =
CurDAG->getMachineFunction().getFunction();
2061 for (
const User *U :
V->users()) {
2077SDValue HexagonDAGToDAGISel::balanceSubTree(
SDNode *
N,
bool TopLevel) {
2078 assert(RootWeights.count(
N) &&
"Cannot balance non-root node.");
2079 assert(RootWeights[
N] != -2 &&
"This node was RAUW'd!");
2083 if (RootWeights[
N] != -1)
2088 if (
N->getNumOperands() < 2)
2100 Weight = getWeight(balanceSubTree(Op0N).
getNode());
2103 Weight = getWeight(Op0N);
2107 Weight += getWeight(balanceSubTree(Op1N).
getNode());
2110 Weight += getWeight(Op1N);
2112 RootWeights[
N] = Weight;
2116 int Height0 = 0, Height1 = 0;
2118 RootWeights[Op0N] >= 0)
2119 Height0 = getHeight(Op0N);
2121 RootWeights[Op1N] >= 0)
2122 Height1 = getHeight(Op1N);
2124 RootHeights[
N] = std::max(Height0, Height1) + 1;
2126 LLVM_DEBUG(
dbgs() <<
"--> No need to balance root (Weight=" << Weight
2127 <<
" Height=" << RootHeights[
N] <<
"): ");
2136 unsigned NOpcode =
N->getOpcode();
2138 LeafPrioQueue Leaves(NOpcode);
2146 bool CanFactorize =
false;
2147 WeightedLeaf Mul1, Mul2;
2148 unsigned MaxPowerOf2 = 0;
2153 bool HaveTopLevelShift =
false;
2159 HaveTopLevelShift =
true;
2163 int InsertionOrder = 0;
2164 SmallDenseMap<SDValue, int> NodeHeights;
2165 bool Imbalanced =
false;
2166 int CurrentWeight = 0;
2167 while (!Worklist.
empty()) {
2173 int Weight = RootWeights[Child.
getNode()];
2175 Child = balanceSubTree(Child.
getNode());
2177 Weight = getWeight(Child.
getNode());
2178 }
else if (Weight == -2) {
2183 return balanceSubTree(
N, TopLevel);
2186 NodeHeights[Child] = 1;
2187 CurrentWeight += Weight;
2190 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&
2197 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);
2198 MaxPowerOf2 = PowerOf2;
2200 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);
2201 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);
2204 if (MaxPowerOf2 > 3)
2207 CanFactorize =
true;
2210 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2213 int Weight = getWeight(Child.
getNode());
2215 NodeHeights[Child] = getHeight(Child.
getNode());
2216 CurrentWeight += Weight;
2219 GA = WeightedLeaf(Child, Weight, InsertionOrder++);
2221 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2225 unsigned ChildOpcode = Child.
getOpcode();
2226 assert(ChildOpcode == NOpcode ||
2231 int Weight = getWeight(Child.
getNode());
2232 NodeHeights[Child] = getHeight(Child.
getNode());
2233 CurrentWeight += Weight;
2234 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2241 Op1 = getMultiplierForSHL(Child.
getNode());
2242 assert(Op1.
getNode() &&
"getMultiplierForSHL returned null");
2247 assert(!NodeHeights.
count(Child) &&
"Parent visited before children?");
2254 if (std::abs(NodeHeights[Op1] - NodeHeights[Child->
getOperand(0)]) > 1)
2257 NodeHeights[Child] = std::max(NodeHeights[Op1],
2264 <<
" weight=" << CurrentWeight
2265 <<
" imbalanced=" << Imbalanced <<
"\n");
2271 LLVM_DEBUG(
dbgs() <<
"--> Found common factor for two MUL children!\n");
2272 int Weight = Mul1.Weight + Mul2.Weight;
2273 int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;
2274 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);
2275 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);
2277 Mul1Factored, Mul2Factored);
2282 NodeHeights[
New] = Height;
2283 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));
2284 }
else if (Mul1.Value.
getNode()) {
2290 CanFactorize =
false;
2296 bool CombinedGA =
false;
2300 GlobalAddressSDNode *GANode =
2304 if (getUsesInFunction(GANode->
getGlobal()) == 1 &&
Offset->hasOneUse() &&
2307 <<
Offset->getSExtValue() <<
"): ");
2316 GA.Weight += Leaves.top().Weight;
2318 NodeHeights[GA.Value] = getHeight(GA.Value.
getNode());
2327 RootWeights[
N] = CurrentWeight;
2328 RootHeights[
N] = NodeHeights[
SDValue(
N, 0)];
2335 WeightedLeaf
SHL = Leaves.findSHL(31);
2336 if (
SHL.Value.getNode()) {
2337 int Height = std::max(NodeHeights[GA.Value], NodeHeights[
SHL.Value]) + 1;
2340 GA.Value,
SHL.Value);
2341 GA.Weight =
SHL.Weight;
2342 NodeHeights[GA.Value] = Height;
2351 if (TopLevel && !CanFactorize && Leaves.hasConst()) {
2353 Leaves.pushToBottom(Leaves.pop());
2356 const DataLayout &
DL =
CurDAG->getDataLayout();
2360 while (Leaves.size() > 1) {
2361 WeightedLeaf L0 = Leaves.pop();
2365 WeightedLeaf L1 = Leaves.findMULbyConst();
2369 assert(L0.Weight <= L1.Weight &&
"Priority queue is broken!");
2372 int V0Weight = L0.Weight;
2374 int V1Weight = L1.Weight;
2377 if ((RootWeights.count(V0.
getNode()) && RootWeights[V0.
getNode()] == -2) ||
2378 (RootWeights.count(V1.
getNode()) && RootWeights[V1.
getNode()] == -2)) {
2380 return balanceSubTree(
N, TopLevel);
2385 EVT VT =
N->getValueType(0);
2395 "Children must have been visited before re-combining them!");
2396 int Height = std::max(NodeHeights[V0], NodeHeights[V1]) + 1;
2400 NewNode =
CurDAG->getNode(
2406 NewNode =
CurDAG->getNode(NOpcode, SDLoc(
N), VT, V0, V1);
2408 NodeHeights[NewNode] = Height;
2410 int Weight = V0Weight + V1Weight;
2411 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));
2414 <<
",Height=" << Height <<
"):\n");
2418 assert(Leaves.size() == 1);
2419 SDValue NewRoot = Leaves.top().Value;
2422 int Height = NodeHeights[NewRoot];
2430 NewRoot =
CurDAG->getNode(
2445 RootWeights[
N] = -2;
2450 RootWeights[NewRoot.
getNode()] = Leaves.top().Weight;
2451 RootHeights[NewRoot.
getNode()] = Height;
2456void HexagonDAGToDAGISel::rebalanceAddressTrees() {
2467 if (RootWeights.count(
BasePtr.getNode()))
2470 LLVM_DEBUG(
dbgs() <<
"** Rebalancing address calculation in node: ");
2476 if (
BasePtr->getNumOperands() < 2)
2482 while (!Worklist.
empty()) {
2484 unsigned Opcode =
N->getOpcode();
2489 if (
N->getNumOperands() < 2)
2492 Worklist.
push_back(
N->getOperand(0).getNode());
2493 Worklist.
push_back(
N->getOperand(1).getNode());
2496 if (
N->hasOneUse() && Opcode ==
N->user_begin()->getOpcode())
2500 RootWeights.try_emplace(
N, -1);
2504 RootWeights[
BasePtr.getNode()] = -1;
2508 if (
N->getNumOperands() >= 3)
2509 N =
CurDAG->UpdateNodeOperands(
N,
N->getOperand(0), NewBasePtr,
2512 if (
N->getNumOperands() >= 4)
2513 N =
CurDAG->UpdateNodeOperands(
N,
N->getOperand(0),
N->getOperand(1),
2514 NewBasePtr,
N->getOperand(3));
2521 CurDAG->RemoveDeadNodes();
2522 GAUsesInFunction.clear();
2523 RootHeights.clear();
2524 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
unsigned getNumOperands() const
SelectionDAGISelLegacy(char &ID, std::unique_ptr< SelectionDAGISel > S)
const TargetLowering * TLI
void ReplaceUses(SDValue F, SDValue T)
ReplaceUses - replace all uses of the old node F with the use of the new node T.
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
const TargetLowering * getTargetLowering() const
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ SIGN_EXTEND
Conversion operators.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
initializer< Ty > init(const Ty &Val)
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned M1(unsigned Val)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionPass * createHexagonISelDag(HexagonTargetMachine &TM, CodeGenOptLevel OptLevel)
createHexagonISelDag - This pass converts a legalized DAG into a Hexagon-specific DAG,...
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
@ Default
The result 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.