83#define DEBUG_TYPE "handle-qfp"
91 "disable-handle-qfp",
cl::init(
false),
92 cl::desc(
"Disable handling of Qfloat spills/refills after register "
96 "enable-postra-xqf-check",
cl::init(
false),
97 cl::desc(
"Enable ABI compliance for xqf operands post regalloc."));
110 {Hexagon::V6_vadd_qf16_mix, {
false,
true}},
111 {Hexagon::V6_vadd_qf16, {
false,
false}},
112 {Hexagon::V6_vadd_qf32_mix, {
false,
true}},
113 {Hexagon::V6_vadd_qf32, {
false,
false}},
114 {Hexagon::V6_vsub_qf16_mix, {
false,
true}},
115 {Hexagon::V6_vsub_hf_mix, {
true,
false}},
116 {Hexagon::V6_vsub_qf16, {
false,
false}},
117 {Hexagon::V6_vsub_qf32_mix, {
false,
true}},
118 {Hexagon::V6_vsub_sf_mix, {
true,
false}},
119 {Hexagon::V6_vsub_qf32, {
false,
false}},
120 {Hexagon::V6_vmpy_qf16_mix_hf, {
false,
true}},
121 {Hexagon::V6_vmpy_qf16, {
false,
false}},
122 {Hexagon::V6_vmpy_qf32_mix_hf, {
false,
true}},
123 {Hexagon::V6_vmpy_qf32_qf16, {
false,
false}},
124 {Hexagon::V6_vmpy_qf32, {
false,
false}},
125 {Hexagon::V6_vmpy_rt_qf16, {
false,
true}},
128 {Hexagon::V6_vabs_qf32_qf32, {
false,
true}},
129 {Hexagon::V6_vabs_qf16_qf16, {
false,
true}},
130 {Hexagon::V6_vneg_qf32_qf32, {
false,
true}},
131 {Hexagon::V6_vneg_qf16_qf16, {
false,
true}},
132 {Hexagon::V6_vilog2_qf32, {
false,
true}},
133 {Hexagon::V6_vilog2_qf16, {
false,
true}},
134 {Hexagon::V6_vconv_qf32_qf32, {
false,
true}},
135 {Hexagon::V6_vconv_qf16_qf16, {
false,
true}},
142 Hexagon::V6_vconv_hf_qf16, Hexagon::V6_vconv_hf_qf32,
143 Hexagon::V6_vconv_sf_qf32,
145 Hexagon::V6_vconv_bf_qf32, Hexagon::V6_vconv_f8_qf16};
151 HexagonPostRAHandleQFP() : MachineFunctionPass(ID) {
155 StringRef getPassName()
const override {
156 return "Hexagon handle QFloat spills and refills post RA.";
158 void getAnalysisUsage(AnalysisUsage &AU)
const override {
161 AU.
addRequired<MachineDominanceFrontierWrapperPass>();
164 bool runOnMachineFunction(MachineFunction &MF)
override;
171 using QFUses = std::map<MachineInstr *, std::pair<bool, bool>>;
175 DataFlowGraph *DFG =
nullptr;
179 std::vector<std::pair<MachineInstr *, NodeAddr<DefNode *>>> SpillMIs;
181 std::vector<NodeAddr<DefNode *>> RefillMIs;
191 MapVector<MachineInstr *, unsigned> QFNonSatMIs;
194 std::set<NodeId> PossibleMultiReachDefs;
198 SmallPtrSet<MachineInstr *, 4> IgnoreInsertConvList;
201 enum class RegType { qf32, qf16, qf32_double, qf16_double, ieee, undefined };
204 std::map<std::pair<NodeId, NodeId>, RegType> QFCopys;
207 DenseMap<MachineInstr *, RegType> ReachDefOfCopies;
212 DenseMap<MachineInstr *, std::pair<NodeAddr<DefNode *>, RegType>>
217 DenseMap<MachineInstr *, std::pair<bool, bool>> SubRegKillSet;
219 const HexagonInstrInfo *HII =
nullptr;
220 const HexagonRegisterInfo *HRI =
nullptr;
221 MachineRegisterInfo *MRI =
nullptr;
222 Liveness *LV =
nullptr;
223 const HexagonSubtarget *HST =
nullptr;
225 void collectQFPStackSpill(NodeAddr<StmtNode *> *);
226 void collectQFPStackRefill(NodeAddr<StmtNode *> *);
227 void collectCopies(NodeAddr<StmtNode *> *);
228 bool HandleRefills();
231 bool HandleNonSatInstr();
232 bool HandleMultiReachingDefs();
233 bool HandleReachDefOfCopies();
234 bool HandleConvertToQfCopies();
235 RegType HasQfUses(NodeAddr<DefNode *>, MachineInstr *);
236 void collectConvQFInstr(NodeAddr<DefNode *> &);
237 void collectQFUses(NodeAddr<DefNode *>, MachineInstr *
DefMI);
238 void conditionallyInsert(MachineInstr &,
Register &);
241 unsigned short getreplacedQFOpcode(
unsigned,
bool,
bool);
242 MCPhysReg findAllocatableReg(MachineInstr *
MI)
const;
243 void insertIEEEToQF(MachineInstr *,
Register, MachineOperand,
bool is32bit);
244 void collectLivenessForSubregs(NodeAddr<UseNode *> &);
245 void insertInstr(MachineInstr *,
unsigned,
unsigned,
unsigned,
RegState);
257 : G(&G), L(&L), HII(HII) {}
274 dbgs() <<
"\n\tDef:";
288 bool comprehensive =
false) {
292 auto UseSet = L->getAllReachedUses(DR, DA);
294 for (
auto UI : UseSet) {
300 if (HRI->isFakeReg(RR))
307 for (
auto I : phiUse) {
310 auto phiUseSet =
I.second;
311 for (
auto phiUI : phiUseSet) {
325 NodeId QFPDefNode = UA.
Addr->getReachingDef();
332 if (ReachDefInstr && ReachDefInstr ==
Instr)
342 for (
auto IA : BA.Addr->members(*G)) {
347 if (
DefMI->isDebugInstr() ||
DefMI->isInlineAsm())
356 for (
auto UI : UseSet) {
362 if (
UseMI->isDebugInstr() ||
UseMI->isInlineAsm())
364 unsigned OpNo = UA.
Addr->getOp().getOperandNo();
365 if (HII->usesQF32Operand(
UseMI, OpNo) && !HII->isQFP32Instr(
DefMI)) {
366 Twine wstr(
Twine(
"Mismatch: sf type used as qf32 at operand ")
369 }
else if (!HII->usesQF32Operand(
UseMI, OpNo) &&
370 HII->isQFP32Instr(
DefMI)) {
371 Twine wstr(
Twine(
"Mismatch: qf32 type used as sf at operand ")
374 }
else if (HII->usesQF16Operand(
UseMI, OpNo) &&
375 !HII->isQFP16Instr(
DefMI)) {
376 Twine wstr(
Twine(
"Mismatch: hf type used as qf16 at operand ")
379 }
else if (!HII->usesQF16Operand(
UseMI, OpNo) &&
380 HII->isQFP16Instr(
DefMI)) {
381 Twine wstr(
Twine(
"Mismatch: qf16 type used as hf at operand ")
390char HexagonPostRAHandleQFP::ID = 0;
407 Register Reg2 =
MI.getNumOperands() == 2 ? DefReg :
MI.getOperand(2).getReg();
409 if (QFUsesMap.find(&
MI) != QFUsesMap.end()) {
410 auto Entry = QFUsesMap[&
MI];
411 bool firstOp = ((Reg1 == DefReg) ?
true :
false) | Entry.first;
412 bool secondOp = ((Reg2 == DefReg) ?
true :
false) | Entry.second;
413 QFUsesMap[&
MI] = std::make_pair(firstOp, secondOp);
420 bool firstOp = (Reg1 == DefReg) ?
true : defaultPair.first;
421 bool secondOp = (Reg2 == DefReg) ?
true : defaultPair.second;
422 QFUsesMap[&
MI] = std::make_pair(firstOp, secondOp);
426unsigned short HexagonPostRAHandleQFP::getreplacedQFOpcode(
unsigned srcOpcode,
429 if (firstOp && secondOp) {
431 case Hexagon::V6_vadd_qf32:
432 case Hexagon::V6_vadd_qf32_mix:
433 return Hexagon::V6_vadd_sf;
434 case Hexagon::V6_vadd_qf16:
435 case Hexagon::V6_vadd_qf16_mix:
436 return Hexagon::V6_vadd_hf;
438 case Hexagon::V6_vsub_qf32:
439 case Hexagon::V6_vsub_qf32_mix:
440 case Hexagon::V6_vsub_sf_mix:
441 return Hexagon::V6_vsub_sf;
442 case Hexagon::V6_vsub_qf16:
443 case Hexagon::V6_vsub_qf16_mix:
444 case Hexagon::V6_vsub_hf_mix:
445 return Hexagon::V6_vsub_hf;
447 case Hexagon::V6_vmpy_qf32:
448 return Hexagon::V6_vmpy_qf32_sf;
449 case Hexagon::V6_vmpy_qf16:
450 case Hexagon::V6_vmpy_qf16_mix_hf:
451 return Hexagon::V6_vmpy_qf16_hf;
452 case Hexagon::V6_vmpy_qf32_qf16:
453 case Hexagon::V6_vmpy_qf32_mix_hf:
454 return Hexagon::V6_vmpy_qf32_hf;
456 case Hexagon::V6_vmpy_rt_qf16:
457 return Hexagon::V6_vmpy_rt_hf;
459 case Hexagon::V6_vabs_qf32_qf32:
460 return Hexagon::V6_vabs_qf32_sf;
461 case Hexagon::V6_vabs_qf16_qf16:
462 return Hexagon::V6_vabs_qf16_hf;
463 case Hexagon::V6_vneg_qf32_qf32:
464 return Hexagon::V6_vneg_qf32_sf;
465 case Hexagon::V6_vneg_qf16_qf16:
466 return Hexagon::V6_vneg_qf16_hf;
467 case Hexagon::V6_vilog2_qf32:
468 return Hexagon::V6_vilog2_sf;
469 case Hexagon::V6_vilog2_qf16:
470 return Hexagon::V6_vilog2_hf;
471 case Hexagon::V6_vconv_qf32_qf32:
472 return Hexagon::V6_vconv_qf32_sf;
473 case Hexagon::V6_vconv_qf16_qf16:
474 return Hexagon::V6_vconv_qf16_hf;
480 }
else if (firstOp) {
482 case Hexagon::V6_vadd_qf32:
483 return Hexagon::V6_vadd_qf32_mix;
484 case Hexagon::V6_vadd_qf16:
485 return Hexagon::V6_vadd_qf16_mix;
487 case Hexagon::V6_vsub_qf32:
489 return Hexagon::V6_vsub_sf_mix;
491 return Hexagon::V6_vsub_sf;
494 case Hexagon::V6_vsub_qf16:
496 return Hexagon::V6_vsub_hf_mix;
498 return Hexagon::V6_vsub_hf;
501 case Hexagon::V6_vsub_qf32_mix:
502 return Hexagon::V6_vsub_sf;
503 case Hexagon::V6_vsub_qf16_mix:
504 return Hexagon::V6_vsub_hf;
509 case Hexagon::V6_vmpy_qf32:
510 return Hexagon::V6_vmpy_qf32_sf;
511 case Hexagon::V6_vmpy_qf16:
512 return Hexagon::V6_vmpy_qf16_mix_hf;
513 case Hexagon::V6_vmpy_qf32_qf16:
514 return Hexagon::V6_vmpy_qf32_mix_hf;
519 }
else if (secondOp) {
521 case Hexagon::V6_vadd_qf32:
522 return Hexagon::V6_vadd_qf32_mix;
523 case Hexagon::V6_vadd_qf16:
524 return Hexagon::V6_vadd_qf16_mix;
526 case Hexagon::V6_vsub_qf32:
527 return Hexagon::V6_vsub_qf32_mix;
528 case Hexagon::V6_vsub_qf16:
529 return Hexagon::V6_vsub_qf16_mix;
530 case Hexagon::V6_vsub_sf_mix:
531 return Hexagon::V6_vsub_sf;
532 case Hexagon::V6_vsub_hf_mix:
533 return Hexagon::V6_vsub_hf;
535 case Hexagon::V6_vmpy_qf32:
536 return Hexagon::V6_vmpy_qf32_sf;
538 case Hexagon::V6_vmpy_qf16:
539 return Hexagon::V6_vmpy_qf16_mix_hf;
540 case Hexagon::V6_vmpy_qf32_qf16:
541 return Hexagon::V6_vmpy_qf32_mix_hf;
552void HexagonPostRAHandleQFP::insertIEEEToQF(MachineInstr *
MI,
Register SrcReg,
553 MachineOperand SrcOp,
554 bool is32bit =
false) {
556 auto MBB =
MI->getParent();
557 MachineInstrBuilder MIB;
561 auto Op = is32bit ? Hexagon::V6_vconv_qf32_sf : Hexagon::V6_vconv_qf16_hf;
563 .
addReg(SrcReg, RegState::Renamable | RegState::Kill);
569 auto V0_Reg = findAllocatableReg(
MI);
574 auto Op = is32bit ? Hexagon::V6_vadd_sf : Hexagon::V6_vadd_hf;
576 .
addReg(SrcReg, RegState::Renamable | RegState::Kill)
577 .
addReg(V0_Reg, RegState::Kill);
586bool HexagonPostRAHandleQFP::HandleRefills() {
590 std::vector<MachineInstr *> eraseList;
592 for (
auto It : QFUsesMap) {
595 MachineInstr *
MI = It.first;
596 auto SrcOpcode =
MI->getOpcode();
597 auto Pair = It.second;
598 auto SrcOp1 =
MI->getOperand(1);
599 Register DestReg =
MI->getOperand(0).getReg();
600 auto MBB =
MI->getParent();
601 MachineInstrBuilder MIB;
607 auto HandleUnaryRefill = [&](MachineInstr *
MI,
bool isIeee) ->
bool {
609 auto finalOpcode = getreplacedQFOpcode(SrcOpcode,
true,
true);
616 eraseList.push_back(
MI);
620 if (
MI->getNumOperands() == 2) {
621 Changed |= HandleUnaryRefill(It.first, It.second.first);
624 auto SrcOp2 =
MI->getOperand(2);
627 auto HandleSub = [&](
auto srcOpcode) ->
bool {
628 auto ConvOp = (srcOpcode == Hexagon::V6_vsub_qf32)
629 ? Hexagon::V6_vconv_sf_qf32
630 : Hexagon::V6_vconv_hf_qf16;
631 auto SubOp = (ConvOp == Hexagon::V6_vconv_sf_qf32) ? Hexagon::V6_vsub_sf
632 : Hexagon::V6_vsub_hf;
634 Register SrcOp2Reg = SrcOp2.getReg();
644 if (!SrcOp2.isKill())
645 insertIEEEToQF(&*(++
MI->getIterator()), SrcOp2.getReg(), SrcOp2);
650 if (Pair.first ==
true && Pair.second ==
true) {
651 auto finalOpcode = getreplacedQFOpcode(SrcOpcode,
true,
true);
659 }
else if (Pair.first ==
true && Pair.second ==
false) {
660 auto finalOpcode = getreplacedQFOpcode(SrcOpcode,
true,
false);
664 if (SrcOpcode == Hexagon::V6_vmpy_qf32) {
665 Register SrcOp2Reg = SrcOp2.getReg();
676 if (!SrcOp2.isKill())
677 insertIEEEToQF(&*(++
MI->getIterator()), SrcOp2.getReg(), SrcOp2,
682 }
else if (finalOpcode == Hexagon::V6_vadd_qf16_mix ||
683 finalOpcode == Hexagon::V6_vadd_qf32_mix ||
684 finalOpcode == Hexagon::V6_vmpy_qf16_mix_hf ||
685 finalOpcode == Hexagon::V6_vmpy_qf32_mix_hf) {
695 }
else if ((SrcOpcode == Hexagon::V6_vsub_qf32 ||
696 SrcOpcode == Hexagon::V6_vsub_qf16) &&
698 Changed |= HandleSub(SrcOpcode);
708 }
else if (Pair.first ==
false && Pair.second ==
true) {
710 auto finalOpcode = getreplacedQFOpcode(SrcOpcode,
false,
true);
713 if (SrcOpcode == Hexagon::V6_vmpy_qf32) {
714 Register SrcOp1Reg = SrcOp1.getReg();
727 if (!SrcOp1.isKill())
728 insertIEEEToQF(&*(++
MI->getIterator()), SrcOp1.getReg(), SrcOp1,
743 eraseList.push_back(
MI);
747 for (MachineInstr *delMI : eraseList)
748 QFUsesMap.erase(delMI);
754void HexagonPostRAHandleQFP::insertInstr(MachineInstr *
MI,
unsigned MIOpcode,
755 unsigned SrcReg,
unsigned DstReg,
758 MachineInstrBuilder MIB;
759 MachineBasicBlock *
MBB =
MI->getParent();
762 auto MINext = ++
MI->getIterator();
766 MIB =
BuildMI(*
MBB, MINext,
DL, HII->get(MIOpcode), DstReg)
774MCPhysReg HexagonPostRAHandleQFP::findAllocatableReg(MachineInstr *
MI)
const {
775 LLVM_DEBUG(
dbgs() <<
"\tUsing V30 register to store a vector of zeroes!");
780bool HexagonPostRAHandleQFP::HandleNonSatInstr() {
782 for (
auto It : QFNonSatMIs) {
783 MachineInstr *
MI = It.first;
784 auto MIOpcode =
MI->getOpcode();
785 auto Op =
MI->getOperand(1);
790 if (MIOpcode == Hexagon::V6_vconv_hf_qf16 ||
791 MIOpcode == Hexagon::V6_vconv_f8_qf16) {
793 insertIEEEToQF(
MI, DefReg,
Op);
797 insertInstr(
MI, Hexagon::V6_vconv_hf_qf16, DefReg, DefReg,
802 }
else if (MIOpcode == Hexagon::V6_vconv_hf_qf32 ||
803 MIOpcode == Hexagon::V6_vconv_bf_qf32) {
804 Register DefLo = HRI->getSubReg(DefReg, Hexagon::vsub_lo);
805 Register DefHi = HRI->getSubReg(DefReg, Hexagon::vsub_hi);
807 if (It.second == ConvOperand::HiLo) {
808 insertIEEEToQF(
MI, DefLo,
Op,
true );
809 insertIEEEToQF(
MI, DefHi,
Op,
true );
813 auto KillState = SubRegKillSet[
MI];
814 if (!KillState.first)
815 insertInstr(
MI, Hexagon::V6_vconv_sf_qf32, DefHi, DefHi,
818 if (!KillState.second)
819 insertInstr(
MI, Hexagon::V6_vconv_sf_qf32, DefLo, DefLo,
822 }
else if (It.second == ConvOperand::Hi) {
823 insertIEEEToQF(
MI, DefHi,
Op,
true );
825 insertInstr(
MI, Hexagon::V6_vconv_sf_qf32, DefHi, DefHi,
829 insertIEEEToQF(
MI, DefLo,
Op,
true );
831 insertInstr(
MI, Hexagon::V6_vconv_sf_qf32, DefLo, DefLo,
835 }
else if (MIOpcode == Hexagon::V6_vconv_sf_qf32) {
836 insertIEEEToQF(
MI, DefReg,
Op,
true );
838 insertInstr(
MI, Hexagon::V6_vconv_sf_qf32, DefReg, DefReg,
846 if (QFNonSatMIs.empty())
854void HexagonPostRAHandleQFP::collectLivenessForSubregs(
855 NodeAddr<UseNode *> &UsedNode) {
856 RegisterRef UR = UsedNode.
Addr->getRegRef(*DFG);
857 NodeAddr<StmtNode *> UseStmt = UsedNode.
Addr->getOwner(*DFG);
858 MachineInstr *UseInstr = UseStmt.
Addr->getCode();
860 Register UseDefLo = HRI->getSubReg(UseOp.getReg(), Hexagon::vsub_lo);
861 Register UseDefHi = HRI->getSubReg(UseOp.getReg(), Hexagon::vsub_hi);
864 bool isHiSubRegKilled =
true, isLoSubRegKilled =
true;
870 for (
auto RD :
P.first) {
871 NodeAddr<DefNode *> RegDef = DFG->
addr<DefNode *>(RD);
875 NodeAddr<StmtNode *> RegStmt = RegDef.Addr->getOwner(*DFG);
876 MachineInstr *ReachDefInstr = RegStmt.
Addr->getCode();
877 if (ReachDefInstr ==
nullptr)
883 if (Hexagon::HvxWRRegClass.
contains(DefReg)) {
885 isHiSubRegKilled = isLoSubRegKilled =
false;
895 for (
auto UIntr : UseSet) {
896 NodeAddr<UseNode *> UA = DFG->
addr<UseNode *>(UIntr);
897 NodeAddr<StmtNode *> UseStmt = UA.
Addr->getOwner(*DFG);
898 MachineInstr *
UseMI = UseStmt.Addr->getCode();
899 if (
UseMI ==
nullptr)
903 if (
UseMI == UseInstr)
906 isLoSubRegKilled =
false;
910 isHiSubRegKilled =
false;
916 SubRegKillSet[UseInstr] = std::make_pair(isHiSubRegKilled, isLoSubRegKilled);
920void HexagonPostRAHandleQFP::collectQFPStackRefill(
921 NodeAddr<StmtNode *> *StNode) {
922 NodeAddr<DefNode *> DfNode =
923 StNode->
Addr->members_if(DFG->
IsDef, *DFG).front();
924 MachineInstr *
MI = StNode->
Addr->getCode();
926 const MachineOperand &OpFI =
MI->getOperand(1);
931 RefillMIs.push_back(DfNode);
936void HexagonPostRAHandleQFP::collectConvQFInstr(NodeAddr<DefNode *> &RegDef) {
939 NodeAddr<StmtNode *> DefStmt = RegDef.
Addr->getOwner(*DFG);
940 MachineInstr *DefInstr = DefStmt.
Addr->getCode();
942 for (
auto UI : UseSet) {
943 NodeAddr<UseNode *> UA = DFG->
addr<UseNode *>(UI);
946 NodeAddr<StmtNode *> UseStmt = UA.
Addr->getOwner(*DFG);
947 MachineInstr *QFConvInstr = UseStmt.
Addr->getCode();
958 collectLivenessForSubregs(UA);
959 unsigned Op = ConvOperand::Undefined;
960 if (QFNonSatMIs.contains(QFConvInstr))
961 Op = QFNonSatMIs[QFConvInstr];
964 if (Hexagon::HvxWRRegClass.
contains(DefReg))
965 Op = ConvOperand::HiLo;
967 else if (DefReg == HRI->getSubReg(
UseReg, Hexagon::vsub_lo))
968 Op |= ConvOperand::Lo;
971 Op |= ConvOperand::Hi;
972 QFNonSatMIs[QFConvInstr] =
Op;
974 QFNonSatMIs[QFConvInstr] = ConvOperand::HiLo;
976 IgnoreInsertConvList.insert(DefInstr);
977 LLVM_DEBUG(std::string OpType =
"";
switch (QFNonSatMIs[QFConvInstr]) {
978 case ConvOperand::HiLo:
981 case ConvOperand::Lo:
984 case ConvOperand::Hi:
988 OpType =
"Undefined";
989 }
dbgs() <<
"Collecting convert instruction with type "
991 QFConvInstr->dump());
999void HexagonPostRAHandleQFP::collectCopies(NodeAddr<StmtNode *> *StNode) {
1001 NodeAddr<DefNode *> CopyDef =
1002 StNode->
Addr->members_if(DFG->
IsDef, *DFG).front();
1003 MachineInstr *CopyInstr = StNode->
Addr->getCode();
1006 for (NodeAddr<UseNode *> UA : StNode->
Addr->members_if(DFG->
IsUse, *DFG)) {
1007 RegisterRef UR = UA.
Addr->getRegRef(*DFG);
1012 dbgs() <<
"*** Unable to collect all reaching defs for use ***\n"
1013 << PrintNode<UseNode *>(UA, *DFG) <<
'\n';
1019 for (
auto RD :
P.first) {
1020 NodeAddr<DefNode *> RegDef = DFG->
addr<DefNode *>(RD);
1024 NodeAddr<StmtNode *> RegStmt = RegDef.
Addr->getOwner(*DFG);
1025 MachineInstr *ReachDefInstr = RegStmt.
Addr->getCode();
1026 if (ReachDefInstr ==
nullptr)
1031 if (ReachDefInstr->
getOpcode() == TargetOpcode::COPY) {
1032 auto pairKey = std::make_pair(CopyDef.
Id, RegDef.
Id);
1033 QFCopys[pairKey] = RegType::ieee;
1039 auto RegT = RegType::undefined;
1045 if (Hexagon::HvxWRRegClass.
contains(
1047 RegT = RegType::qf32_double;
1049 RegT = RegType::qf32;
1052 if (Hexagon::HvxWRRegClass.
contains(
1054 RegT = RegType::qf16_double;
1056 RegT = RegType::qf16;
1062 if (Hexagon::HvxWRRegClass.
contains(CopyReg) ||
1063 Hexagon::HvxVRRegClass.
contains(CopyReg))
1064 RegT = RegType::ieee;
1068 auto pairKey = std::make_pair(CopyDef.
Id, RegDef.
Id);
1069 QFCopys[pairKey] = RegT;
1076void HexagonPostRAHandleQFP::collectQFPStackSpill(
1077 NodeAddr<StmtNode *> *StNode) {
1079 MachineInstr *
MI = StNode->
Addr->getCode();
1082 const MachineOperand &OpFI =
MI->getOperand(0);
1095 if (!
MI->getOperand(2).isReg())
1101 for (NodeAddr<UseNode *> UA : StNode->
Addr->members_if(DFG->
IsUse, *DFG)) {
1102 QFPDefNode = UA.
Addr->getReachingDef();
1105 NodeAddr<DefNode *> RegDef = DFG->
addr<DefNode *>(QFPDefNode);
1106 assert(QFPDefNode != 0 &&
"Reaching def computation error");
1107 NodeAddr<StmtNode *> RegStmt = RegDef.
Addr->getOwner(*DFG);
1108 MachineInstr *ReachDefInstr = RegStmt.
Addr->getCode();
1109 if (ReachDefInstr ==
nullptr)
1112 ReachDefInstr->
dump());
1120 auto RR = RegDef.
Addr->getRegRef(*DFG).Id;
1125 dbgs() <<
"The corresponding XQF instruction is:\n";
1126 ReachDefInstr->
dump());
1129 SpillMIs.push_back(std::make_pair(
MI, RegDef));
1135void HexagonPostRAHandleQFP::collectQFUses(NodeAddr<DefNode *> RegDef,
1136 MachineInstr *
DefMI) {
1142 for (
auto UI : UseSet) {
1143 NodeAddr<UseNode *> UA = DFG->
addr<UseNode *>(UI);
1146 NodeAddr<StmtNode *> UseStmt = UA.
Addr->getOwner(*DFG);
1147 MachineInstr *
UseMI = UseStmt.
Addr->getCode();
1152 if (PossibleMultiReachDefs.count(UseStmt.
Id) == 0) {
1153 PossibleMultiReachDefs.insert(UseStmt.
Id);
1154 LLVM_DEBUG(
dbgs() <<
"\n[Collect instr with possible multidef]:";
1157 conditionallyInsert(*
UseMI, UsedReg);
1167bool HexagonPostRAHandleQFP::HandleMultiReachingDefs() {
1173 for (
auto It : PossibleMultiReachDefs) {
1174 NodeAddr<StmtNode *>
Stmt = DFG->
addr<StmtNode *>(It);
1178 auto Pair = QFUsesMap[
Instr];
1180 unsigned short UseNo = 1;
1186 if ((UseNo == 1 && Pair.first ==
false) ||
1187 (UseNo == 2 && Pair.second ==
false)) {
1192 RegisterRef UR = UA.
Addr->getRegRef(*DFG);
1197 dbgs() <<
"*** Unable to collect all reaching defs for use ***\n"
1198 << PrintNode<UseNode *>(UA, *DFG) <<
'\n';
1205 for (
auto RD :
P.first) {
1206 NodeAddr<DefNode *> RegDef = DFG->
addr<DefNode *>(RD);
1209 auto RR = RegDef.
Addr->getRegRef(*DFG).Id;
1213 NodeAddr<StmtNode *> RegStmt = RegDef.
Addr->getOwner(*DFG);
1214 MachineInstr *ReachDefInstr = RegStmt.
Addr->getCode();
1216 if (ReachDefInstr ==
nullptr)
1221 if (IgnoreInsertConvList.find(ReachDefInstr) !=
1222 IgnoreInsertConvList.end())
1225 ReachDefInstr->
dump());
1229 auto NextReachMI = ++ReachDefInstr->
getIterator();
1232 MachineInstrBuilder MIB;
1238 if (Hexagon::HvxWRRegClass.
contains(
1240 Register RegLo = HRI->getSubReg(OpReg, Hexagon::vsub_lo);
1241 Register RegHi = HRI->getSubReg(OpReg, Hexagon::vsub_hi);
1243 HII->get(Hexagon::V6_vconv_sf_qf32), RegLo)
1244 .
addReg(RegLo, RegState::Renamable | RegState::Kill);
1245 LLVM_DEBUG(
dbgs() <<
"[MultiDef] Inserting convert instruction: ";
1248 HII->get(Hexagon::V6_vconv_sf_qf32), RegHi)
1249 .
addReg(RegHi, RegState::Renamable | RegState::Kill);
1252 HII->get(Hexagon::V6_vconv_sf_qf32), OpReg)
1253 .
addReg(OpReg, RegState::Renamable | RegState::Kill);
1258 HII->get(Hexagon::V6_vconv_hf_qf16), OpReg)
1259 .
addReg(OpReg, RegState::Renamable | RegState::Kill);
1261 LLVM_DEBUG(
dbgs() <<
"[MultiDef] Inserting convert instruction: ";
1263 ReachDefInstr->
dump());
1268 collectQFUses(RegDef, ReachDefInstr);
1269 collectConvQFInstr(RegDef);
1270 IgnoreInsertConvList.insert(ReachDefInstr);
1279bool HexagonPostRAHandleQFP::HandleConvertToQfCopies() {
1280 if (ConvertToQfCopies.empty())
1284 dbgs() <<
"\n*** Inserting convert to qf for selected copies ***\n");
1289 auto CanTransform = [&](MachineInstr *
MI,
unsigned OpNo) ->
bool {
1290 if (QFUsesMap.find(
MI) != QFUsesMap.end()) {
1292 if (OpNo == 1 &&
Entry.first ==
true)
1294 if (OpNo == 2 &&
Entry.second ==
true)
1300 for (
auto It : ConvertToQfCopies) {
1305 for (
auto UI : UseSet) {
1306 NodeAddr<UseNode *> UA = DFG->
addr<UseNode *>(UI);
1309 NodeAddr<StmtNode *> UseStmt = UA.
Addr->getOwner(*DFG);
1310 MachineInstr *
UseMI = UseStmt.
Addr->getCode();
1311 unsigned OpNo = UA.
Addr->getOp().getOperandNo();
1313 if (!CanTransform(
UseMI, OpNo)) {
1321 LLVM_DEBUG(
dbgs() <<
"\n[HandleConvertToQfCopies]\tProcessing Copy:";
1323 auto CopyOp = It.first->getOperand(0);
1324 auto NextMIIter = std::next(It.first->getIterator());
1325 switch (It.second.second) {
1326 case RegType::qf32_double: {
1327 Register DefLo = HRI->getSubReg(CopyOp.getReg(), Hexagon::vsub_lo);
1328 Register DefHi = HRI->getSubReg(CopyOp.getReg(), Hexagon::vsub_hi);
1329 insertIEEEToQF(&*NextMIIter, DefLo, CopyOp,
true);
1330 insertIEEEToQF(&*NextMIIter, DefHi, CopyOp,
true);
1333 case RegType::qf16_double: {
1334 Register DefLo = HRI->getSubReg(CopyOp.getReg(), Hexagon::vsub_lo);
1335 Register DefHi = HRI->getSubReg(CopyOp.getReg(), Hexagon::vsub_hi);
1336 insertIEEEToQF(&*NextMIIter, DefLo, CopyOp,
false);
1337 insertIEEEToQF(&*NextMIIter, DefHi, CopyOp,
false);
1341 insertIEEEToQF(&*NextMIIter, CopyOp.getReg(), CopyOp,
1345 insertIEEEToQF(&*NextMIIter, CopyOp.getReg(), CopyOp,
true);
1351 collectQFUses(It.second.first, It.first);
1352 collectConvQFInstr(It.second.first);
1358bool HexagonPostRAHandleQFP::HandleReachDefOfCopies() {
1359 if (ReachDefOfCopies.empty())
1362 MachineInstrBuilder MIB;
1363 for (
auto It : ReachDefOfCopies) {
1365 auto &dl = It.first->getDebugLoc();
1366 auto NextMI = ++(It.first)->getIterator();
1367 auto RegOp = It.first->getOperand(0);
1370 if (It.second == RegType::qf32)
1372 BuildMI(*
MBB, NextMI, dl, HII->get(Hexagon::V6_vconv_sf_qf32), OpReg)
1373 .
addReg(OpReg, RegState::Renamable | RegState::Kill);
1374 else if (It.second == RegType::qf16)
1376 BuildMI(*
MBB, NextMI, dl, HII->get(Hexagon::V6_vconv_hf_qf16), OpReg)
1377 .
addReg(OpReg, RegState::Renamable | RegState::Kill);
1378 else if (It.second == RegType::qf32_double) {
1379 Register RegLo = HRI->getSubReg(OpReg, Hexagon::vsub_lo);
1380 Register RegHi = HRI->getSubReg(OpReg, Hexagon::vsub_hi);
1382 BuildMI(*
MBB, NextMI, dl, HII->get(Hexagon::V6_vconv_sf_qf32), RegLo)
1383 .
addReg(RegLo, RegState::Renamable | RegState::Kill);
1387 BuildMI(*
MBB, NextMI, dl, HII->get(Hexagon::V6_vconv_sf_qf32), RegHi)
1388 .
addReg(RegHi, RegState::Renamable | RegState::Kill);
1389 }
else if (It.second == RegType::qf16_double) {
1390 Register RegLo = HRI->getSubReg(OpReg, Hexagon::vsub_lo);
1391 Register RegHi = HRI->getSubReg(OpReg, Hexagon::vsub_hi);
1393 BuildMI(*
MBB, NextMI, dl, HII->get(Hexagon::V6_vconv_hf_qf16), RegLo)
1394 .
addReg(RegLo, RegState::Renamable | RegState::Kill);
1398 BuildMI(*
MBB, NextMI, dl, HII->get(Hexagon::V6_vconv_hf_qf16), RegHi)
1399 .
addReg(RegHi, RegState::Renamable | RegState::Kill);
1408HexagonPostRAHandleQFP::RegType
1409HexagonPostRAHandleQFP::HasQfUses(NodeAddr<DefNode *> CopyDef,
1410 MachineInstr *CopyMI) {
1414 if (UseSet.
size() == 0)
1415 return RegType::undefined;
1417 bool hasQf16Use =
false;
1418 bool hasQf32Use =
false;
1421 for (
auto UI : UseSet) {
1422 NodeAddr<UseNode *> UA = DFG->
addr<UseNode *>(UI);
1425 NodeAddr<StmtNode *> UseStmt = UA.
Addr->getOwner(*DFG);
1426 MachineInstr *
UseMI = UseStmt.
Addr->getCode();
1427 unsigned OpNo = UA.
Addr->getOp().getOperandNo();
1432 return RegType::ieee;
1443 if (QFUsesMap.find(
UseMI) != QFUsesMap.end()) {
1445 if (OpNo == 1 &&
Entry.first ==
true)
1446 return RegType::ieee;
1447 if (OpNo == 2 &&
Entry.second ==
true)
1448 return RegType::ieee;
1456 return RegType::qf16_double;
1458 return RegType::qf16;
1459 }
else if (hasQf32Use) {
1461 return RegType::qf32_double;
1463 return RegType::qf32;
1466 return RegType::undefined;
1476bool HexagonPostRAHandleQFP::HandleCopies() {
1483 for (
auto It : QFCopys) {
1486 NodeAddr<DefNode *> CopyNode = DFG->
addr<DefNode *>(It.first.first);
1487 NodeAddr<StmtNode *> StNode = CopyNode.
Addr->getOwner(*DFG);
1488 [[maybe_unused]]
auto *CopyMI = StNode.Addr->getCode();
1490 std::string
Type;
switch (It.second) {
1491 case RegType::qf32_double:
1492 Type =
"qf32_double";
1500 case RegType::qf16_double:
1501 Type =
"qf16_double";
1505 }
dbgs() <<
"\t Type: "
1509 RegType RTy = It.second;
1510 if (RTy != RegType::ieee) {
1513 NodeAddr<DefNode *> ReachDefNode = DFG->
addr<DefNode *>(It.first.second);
1514 NodeAddr<StmtNode *> StNode = ReachDefNode.
Addr->getOwner(*DFG);
1515 auto *ReachingDef = StNode.Addr->getCode();
1517 if (IgnoreInsertConvList.find(ReachingDef) != IgnoreInsertConvList.end())
1521 ReachDefOfCopies.insert(std::make_pair(ReachingDef, RTy));
1526 LLVM_DEBUG(
dbgs() <<
"\n[COPY]\tAnalyzing uses of the reaching defs \
1528 collectQFUses(ReachDefNode, ReachingDef);
1529 collectConvQFInstr(ReachDefNode);
1530 IgnoreInsertConvList.insert(ReachingDef);
1536 for (
auto It : QFCopys) {
1539 NodeAddr<DefNode *> CopyNode = DFG->
addr<DefNode *>(It.first.first);
1540 NodeAddr<StmtNode *> StNode = CopyNode.
Addr->getOwner(*DFG);
1541 auto *CopyMI = StNode.Addr->getCode();
1543 RegType RTy = It.second;
1550 RTy = HasQfUses(CopyNode, CopyMI);
1551 if (RTy != RegType::ieee && RTy != RegType::undefined &&
1553 if (!ConvertToQfCopies.contains(CopyMI)) {
1554 ConvertToQfCopies[CopyMI] = std::make_pair(CopyNode, RTy);
1556 CopyMI->
dump(); std::string
Type;
switch (RTy) {
1557 case RegType::qf32_double:
1558 Type =
"qf32_double";
1566 case RegType::qf16_double:
1567 Type =
"qf16_double";
1571 }
dbgs() <<
"\t Type: "
1577 collectQFUses(CopyNode, CopyMI);
1578 collectConvQFInstr(CopyNode);
1581 Changed |= HandleReachDefOfCopies();
1582 Changed |= HandleMultiReachingDefs();
1583 Changed |= HandleConvertToQfCopies();
1592bool HexagonPostRAHandleQFP::HandleSpills() {
1596 for (
auto It : SpillMIs) {
1598 MachineInstr *
MI = It.first;
1599 auto OpC =
MI->getOpcode();
1601 auto NodeDef = It.second;
1604 auto RegOp =
MI->getOperand(2);
1608 if (OpC == Hexagon::PS_vstorerw_ai) {
1609 if (!Hexagon::HvxWRRegClass.
contains(DefR))
1610 assert(
false &&
" Unhandled Vector Register class passed\n");
1614 collectQFUses(NodeDef,
DefMI);
1616 if (IgnoreInsertConvList.find(
DefMI) != IgnoreInsertConvList.end())
1621 collectConvQFInstr(NodeDef);
1622 Register DefLo = HRI->getSubReg(DefR, Hexagon::vsub_lo);
1623 Register DefHi = HRI->getSubReg(DefR, Hexagon::vsub_hi);
1632 if (DefLo == DReg || Hexagon::HvxWRRegClass.
contains(DReg))
1633 insertInstr(
DefMI, Hexagon::V6_vconv_hf_qf16, DefLo, DefLo,
1636 if (DefHi == DReg || Hexagon::HvxWRRegClass.
contains(DReg))
1637 insertInstr(
DefMI, Hexagon::V6_vconv_hf_qf16, DefHi, DefHi,
1640 if (DefLo == DReg || Hexagon::HvxWRRegClass.
contains(DReg))
1641 insertInstr(
DefMI, Hexagon::V6_vconv_sf_qf32, DefLo, DefLo,
1644 if (DefHi == DReg || Hexagon::HvxWRRegClass.
contains(DReg))
1645 insertInstr(
DefMI, Hexagon::V6_vconv_sf_qf32, DefHi, DefHi,
1648 IgnoreInsertConvList.insert(
DefMI);
1653 collectQFUses(NodeDef,
DefMI);
1654 if (IgnoreInsertConvList.find(
DefMI) != IgnoreInsertConvList.end())
1656 collectConvQFInstr(NodeDef);
1658 insertInstr(
DefMI, Hexagon::V6_vconv_sf_qf32, DefR, DefR,
1661 IgnoreInsertConvList.insert(
DefMI);
1666 collectQFUses(NodeDef,
DefMI);
1667 if (IgnoreInsertConvList.find(
DefMI) != IgnoreInsertConvList.end())
1669 collectConvQFInstr(NodeDef);
1671 insertInstr(
DefMI, Hexagon::V6_vconv_hf_qf16, DefR, DefR,
1674 IgnoreInsertConvList.insert(
DefMI);
1684bool HexagonPostRAHandleQFP::runOnMachineFunction(MachineFunction &MF) {
1690 dbgs() <<
"\n=== Entering Hexagon Fixup QF spills and refills pass ===\n"
1693 case QFloatMode::StrictIEEE:
1694 dbgs() <<
"Strict IEEE";
1696 case QFloatMode::IEEE:
1699 case QFloatMode::Lossy:
1710 if (!_HST.useHVXOps())
1713 HII = _HST.getInstrInfo();
1721 HRI = _HST.getRegisterInfo();
1723 const auto &MDF = getAnalysis<MachineDominanceFrontierWrapperPass>().getMDF();
1724 MachineDominatorTree *MDT =
1725 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
1731 DataFlowGraph
G(MF, *HII, *HRI, *MDT, MDF);
1735 Liveness
L(*MRI, *DFG);
1741 NodeAddr<FuncNode *> FA = DFG->
getFunc();
1743 <<
Print<NodeAddr<FuncNode *>>(FA, *DFG) <<
"\n");
1744 for (NodeAddr<BlockNode *> BA : FA.
Addr->members(*DFG)) {
1745 for (
auto IA : BA.Addr->members(*DFG)) {
1751 NodeAddr<StmtNode *> SA =
IA;
1752 MachineInstr *
I = SA.
Addr->getCode();
1754 switch (
I->getOpcode()) {
1755 case Hexagon::PS_vstorerw_ai:
1756 case Hexagon::PS_vstorerv_ai:
1757 collectQFPStackSpill(&SA);
1759 case Hexagon::PS_vloadrw_ai:
1760 case Hexagon::PS_vloadrv_ai:
1761 collectQFPStackRefill(&SA);
1763 case TargetOpcode::COPY:
1782 for (NodeAddr<DefNode *> DfNode : RefillMIs) {
1784 NodeAddr<StmtNode *>
Stmt = DfNode.
Addr->getOwner(*DFG);
1786 collectQFUses(DfNode,
DefMI);
1787 collectConvQFInstr(DfNode);
1794 PossibleMultiReachDefs.clear();
1795 ReachDefOfCopies.clear();
1796 ConvertToQfCopies.clear();
1798 LLVM_DEBUG(
dbgs() <<
"\n === QF Uses map === ";
for (
auto It : QFUsesMap) {
1799 dbgs() <<
"\nInstruction: ";
1801 dbgs() <<
"\t Property: " << It.second.first <<
" ," << It.second.second;
1809 Changed |= HandleNonSatInstr();
1810 QFNonSatMIs.clear();
1812 for (
auto It : QFUsesMap)
1813 It.first->eraseFromParent();
1815 IgnoreInsertConvList.clear();
1819 dbgs() <<
"\nChecking for ABI compliance for XQF post register \
1820allocation for function: "
1822 DataFlowGraph DFG(MF, *HII, *HRI, *MDT, MDF);
1824 Liveness LV(*MRI, DFG);
1826 XqfPostRADiagnosis VDiag(DFG, LV, HII);
1827 VDiag.runCompliance();
1836 "Hexagon Post RA Handle QFloat",
false,
false)
1843 return new HexagonPostRAHandleQFP();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static Register UseReg(const MachineOperand &MO)
SmallVector< unsigned short, 5 > QFNonSatInstr
cl::opt< bool > DisablePostRAHandleQFloat("disable-handle-qfp", cl::init(false), cl::desc("Disable handling of Qfloat spills/refills after register " "allocation."))
DenseMap< unsigned short, std::pair< bool, bool > > QFPSatInstsMap
static cl::opt< bool > EnablePostRAXqfCompliance("enable-postra-xqf-check", cl::init(false), cl::desc("Enable ABI compliance for xqf operands post regalloc."))
cl::opt< QFloatMode > QFloatModeValue
static void getAllRealUses(NodeAddr< DefNode * > DA, NodeSet &UNodeSet, Liveness *L, DataFlowGraph *G, bool comprehensive=false)
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
Promote Memory to Register
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
void runCompliance() const
void print_warning(Twine &, MachineInstr *, MachineInstr *) const
XqfPostRADiagnosis(DataFlowGraph &G, Liveness &L, const HexagonInstrInfo *HII)
XqfPostRADiagnosis()=delete
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
FunctionPass class - This class is used to implement most global optimizations.
bool hasQFPInstrs(const MachineFunction &MF) const
bool isQFP32Instr(MachineInstr *MI) const
bool usesQF16Operand(MachineInstr *MI, unsigned Index=0) const
bool isQFP16Instr(MachineInstr *MI) const
bool usesQF32Operand(MachineInstr *MI, unsigned Index=0) const
bool isMIBefore(const MachineInstr *A, const MachineInstr *B) const
bool isQFPInstr(MachineInstr *MI) const
bool usesQFOperand(MachineInstr *MI, unsigned Index=0) const
bool isFakeReg(MCPhysReg Reg) const
Returns true if the given reserved physical register Reg is live across function calls/returns.
bool useHVXV79Ops() const
bool useHVXV81Ops() const
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
Register getReg() const
getReg - Returns the register number.
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
A NodeSet contains a set of SUnit DAG nodes with additional information that assigns a priority to th...
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Wrapper class representing virtual and physical registers.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
NodeAddr< InstrNode * > Instr
Print(const T &, const DataFlowGraph &) -> Print< T >
NodeAddr< StmtNode * > Stmt
std::set< NodeId > NodeSet
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
RegState
Flags to represent properties of register accesses.
void initializeHexagonPostRAHandleQFPPass(PassRegistry &)
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
char & HexagonPostRAHandleQFPID
FunctionPass * createHexagonPostRAHandleQFP()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
RegState getRegState(const MachineOperand &RegOp)
Get all register state flags from machine operand RegOp.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
NodeList members_if(Predicate P, const DataFlowGraph &G) const
LLVM_ABI void build(const Config &config)
static bool IsDef(const Node BA)
static bool IsUse(const Node BA)
static bool IsCode(const Node BA)
NodeAddr< T > addr(NodeId N) const
LLVM_ABI Node getOwner(const DataFlowGraph &G)
DenseMap< RegisterId, NodeRefSet > RefMap
LLVM_ABI std::pair< NodeSet, bool > getAllReachingDefsRec(RegisterRef RefRR, NodeAddr< RefNode * > RefA, NodeSet &Visited, const NodeSet &Defs)
LLVM_ABI void computeLiveIns()
MachineInstr * getCode() const