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<NodeAddr<StmtNode *>> PossibleMultiReachDefs;
198 SmallPtrSet<MachineInstr *, 4> IgnoreInsertConvList;
201 enum class RegType { qf32, qf16, qf32_double, qf16_double, ieee, undefined };
204 std::map<std::pair<NodeAddr<DefNode *>, NodeAddr<DefNode *>>, RegType>
208 DenseMap<MachineInstr *, RegType> ReachDefOfCopies;
213 DenseMap<MachineInstr *, std::pair<NodeAddr<DefNode *>, RegType>>
218 DenseMap<MachineInstr *, std::pair<bool, bool>> SubRegKillSet;
220 const HexagonInstrInfo *HII =
nullptr;
221 const HexagonRegisterInfo *HRI =
nullptr;
222 MachineRegisterInfo *MRI =
nullptr;
223 Liveness *LV =
nullptr;
224 const HexagonSubtarget *HST =
nullptr;
226 void collectQFPStackSpill(NodeAddr<StmtNode *> *);
227 void collectQFPStackRefill(NodeAddr<StmtNode *> *);
228 void collectCopies(NodeAddr<StmtNode *> *);
229 bool HandleRefills();
232 bool HandleNonSatInstr();
233 bool HandleMultiReachingDefs();
234 bool HandleReachDefOfCopies();
235 bool HandleConvertToQfCopies();
236 RegType HasQfUses(NodeAddr<DefNode *>, MachineInstr *);
237 void collectConvQFInstr(NodeAddr<DefNode *> &);
238 void collectQFUses(NodeAddr<DefNode *>, MachineInstr *
DefMI);
239 void conditionallyInsert(MachineInstr &,
Register &);
242 unsigned short getreplacedQFOpcode(
unsigned,
bool,
bool);
243 MCPhysReg findAllocatableReg(MachineInstr *
MI)
const;
244 void insertIEEEToQF(MachineInstr *,
Register, MachineOperand,
bool is32bit);
245 void collectLivenessForSubregs(NodeAddr<UseNode *> &);
246 void insertInstr(MachineInstr *,
unsigned,
unsigned,
unsigned,
RegState);
258 : G(&G), L(&L), HII(HII) {}
275 dbgs() <<
"\n\tDef:";
289 bool comprehensive =
false) {
293 auto UseSet = L->getAllReachedUses(DR, DA);
295 for (
auto UI : UseSet) {
301 if (HRI->isFakeReg(RR))
308 for (
auto I : phiUse) {
311 auto phiUseSet =
I.second;
312 for (
auto phiUI : phiUseSet) {
326 NodeId QFPDefNode = UA.
Addr->getReachingDef();
333 if (ReachDefInstr && ReachDefInstr ==
Instr)
343 for (
auto IA : BA.Addr->members(*G)) {
348 if (
DefMI->isDebugInstr() ||
DefMI->isInlineAsm())
357 for (
auto UI : UseSet) {
363 if (
UseMI->isDebugInstr() ||
UseMI->isInlineAsm())
365 unsigned OpNo = UA.
Addr->getOp().getOperandNo();
366 if (HII->usesQF32Operand(
UseMI, OpNo) && !HII->isQFP32Instr(
DefMI)) {
367 Twine wstr(
Twine(
"Mismatch: sf type used as qf32 at operand ")
370 }
else if (!HII->usesQF32Operand(
UseMI, OpNo) &&
371 HII->isQFP32Instr(
DefMI)) {
372 Twine wstr(
Twine(
"Mismatch: qf32 type used as sf at operand ")
375 }
else if (HII->usesQF16Operand(
UseMI, OpNo) &&
376 !HII->isQFP16Instr(
DefMI)) {
377 Twine wstr(
Twine(
"Mismatch: hf type used as qf16 at operand ")
380 }
else if (!HII->usesQF16Operand(
UseMI, OpNo) &&
381 HII->isQFP16Instr(
DefMI)) {
382 Twine wstr(
Twine(
"Mismatch: qf16 type used as hf at operand ")
391char HexagonPostRAHandleQFP::ID = 0;
408 Register Reg2 =
MI.getNumOperands() == 2 ? DefReg :
MI.getOperand(2).getReg();
410 if (QFUsesMap.find(&
MI) != QFUsesMap.end()) {
411 auto Entry = QFUsesMap[&
MI];
412 bool firstOp = ((Reg1 == DefReg) ?
true :
false) | Entry.first;
413 bool secondOp = ((Reg2 == DefReg) ?
true :
false) | Entry.second;
414 QFUsesMap[&
MI] = std::make_pair(firstOp, secondOp);
421 bool firstOp = (Reg1 == DefReg) ?
true : defaultPair.first;
422 bool secondOp = (Reg2 == DefReg) ?
true : defaultPair.second;
423 QFUsesMap[&
MI] = std::make_pair(firstOp, secondOp);
427unsigned short HexagonPostRAHandleQFP::getreplacedQFOpcode(
unsigned srcOpcode,
430 if (firstOp && secondOp) {
432 case Hexagon::V6_vadd_qf32:
433 case Hexagon::V6_vadd_qf32_mix:
434 return Hexagon::V6_vadd_sf;
435 case Hexagon::V6_vadd_qf16:
436 case Hexagon::V6_vadd_qf16_mix:
437 return Hexagon::V6_vadd_hf;
439 case Hexagon::V6_vsub_qf32:
440 case Hexagon::V6_vsub_qf32_mix:
441 case Hexagon::V6_vsub_sf_mix:
442 return Hexagon::V6_vsub_sf;
443 case Hexagon::V6_vsub_qf16:
444 case Hexagon::V6_vsub_qf16_mix:
445 case Hexagon::V6_vsub_hf_mix:
446 return Hexagon::V6_vsub_hf;
448 case Hexagon::V6_vmpy_qf32:
449 return Hexagon::V6_vmpy_qf32_sf;
450 case Hexagon::V6_vmpy_qf16:
451 case Hexagon::V6_vmpy_qf16_mix_hf:
452 return Hexagon::V6_vmpy_qf16_hf;
453 case Hexagon::V6_vmpy_qf32_qf16:
454 case Hexagon::V6_vmpy_qf32_mix_hf:
455 return Hexagon::V6_vmpy_qf32_hf;
457 case Hexagon::V6_vmpy_rt_qf16:
458 return Hexagon::V6_vmpy_rt_hf;
460 case Hexagon::V6_vabs_qf32_qf32:
461 return Hexagon::V6_vabs_qf32_sf;
462 case Hexagon::V6_vabs_qf16_qf16:
463 return Hexagon::V6_vabs_qf16_hf;
464 case Hexagon::V6_vneg_qf32_qf32:
465 return Hexagon::V6_vneg_qf32_sf;
466 case Hexagon::V6_vneg_qf16_qf16:
467 return Hexagon::V6_vneg_qf16_hf;
468 case Hexagon::V6_vilog2_qf32:
469 return Hexagon::V6_vilog2_sf;
470 case Hexagon::V6_vilog2_qf16:
471 return Hexagon::V6_vilog2_hf;
472 case Hexagon::V6_vconv_qf32_qf32:
473 return Hexagon::V6_vconv_qf32_sf;
474 case Hexagon::V6_vconv_qf16_qf16:
475 return Hexagon::V6_vconv_qf16_hf;
481 }
else if (firstOp) {
483 case Hexagon::V6_vadd_qf32:
484 return Hexagon::V6_vadd_qf32_mix;
485 case Hexagon::V6_vadd_qf16:
486 return Hexagon::V6_vadd_qf16_mix;
488 case Hexagon::V6_vsub_qf32:
490 return Hexagon::V6_vsub_sf_mix;
492 return Hexagon::V6_vsub_sf;
495 case Hexagon::V6_vsub_qf16:
497 return Hexagon::V6_vsub_hf_mix;
499 return Hexagon::V6_vsub_hf;
502 case Hexagon::V6_vsub_qf32_mix:
503 return Hexagon::V6_vsub_sf;
504 case Hexagon::V6_vsub_qf16_mix:
505 return Hexagon::V6_vsub_hf;
510 case Hexagon::V6_vmpy_qf32:
511 return Hexagon::V6_vmpy_qf32_sf;
512 case Hexagon::V6_vmpy_qf16:
513 return Hexagon::V6_vmpy_qf16_mix_hf;
514 case Hexagon::V6_vmpy_qf32_qf16:
515 return Hexagon::V6_vmpy_qf32_mix_hf;
520 }
else if (secondOp) {
522 case Hexagon::V6_vadd_qf32:
523 return Hexagon::V6_vadd_qf32_mix;
524 case Hexagon::V6_vadd_qf16:
525 return Hexagon::V6_vadd_qf16_mix;
527 case Hexagon::V6_vsub_qf32:
528 return Hexagon::V6_vsub_qf32_mix;
529 case Hexagon::V6_vsub_qf16:
530 return Hexagon::V6_vsub_qf16_mix;
531 case Hexagon::V6_vsub_sf_mix:
532 return Hexagon::V6_vsub_sf;
533 case Hexagon::V6_vsub_hf_mix:
534 return Hexagon::V6_vsub_hf;
536 case Hexagon::V6_vmpy_qf32:
537 return Hexagon::V6_vmpy_qf32_sf;
539 case Hexagon::V6_vmpy_qf16:
540 return Hexagon::V6_vmpy_qf16_mix_hf;
541 case Hexagon::V6_vmpy_qf32_qf16:
542 return Hexagon::V6_vmpy_qf32_mix_hf;
553void HexagonPostRAHandleQFP::insertIEEEToQF(MachineInstr *
MI,
Register SrcReg,
554 MachineOperand SrcOp,
555 bool is32bit =
false) {
557 auto MBB =
MI->getParent();
558 MachineInstrBuilder MIB;
562 auto Op = is32bit ? Hexagon::V6_vconv_qf32_sf : Hexagon::V6_vconv_qf16_hf;
564 .
addReg(SrcReg, RegState::Renamable | RegState::Kill);
570 auto V0_Reg = findAllocatableReg(
MI);
575 auto Op = is32bit ? Hexagon::V6_vadd_sf : Hexagon::V6_vadd_hf;
577 .
addReg(SrcReg, RegState::Renamable | RegState::Kill)
578 .
addReg(V0_Reg, RegState::Kill);
587bool HexagonPostRAHandleQFP::HandleRefills() {
591 std::vector<MachineInstr *> eraseList;
593 for (
auto It : QFUsesMap) {
596 MachineInstr *
MI = It.first;
597 auto SrcOpcode =
MI->getOpcode();
598 auto Pair = It.second;
599 auto SrcOp1 =
MI->getOperand(1);
600 Register DestReg =
MI->getOperand(0).getReg();
601 auto MBB =
MI->getParent();
602 MachineInstrBuilder MIB;
608 auto HandleUnaryRefill = [&](MachineInstr *
MI,
bool isIeee) ->
bool {
610 auto finalOpcode = getreplacedQFOpcode(SrcOpcode,
true,
true);
617 eraseList.push_back(
MI);
621 if (
MI->getNumOperands() == 2) {
622 Changed |= HandleUnaryRefill(It.first, It.second.first);
625 auto SrcOp2 =
MI->getOperand(2);
628 auto HandleSub = [&](
auto srcOpcode) ->
bool {
629 auto ConvOp = (srcOpcode == Hexagon::V6_vsub_qf32)
630 ? Hexagon::V6_vconv_sf_qf32
631 : Hexagon::V6_vconv_hf_qf16;
632 auto SubOp = (ConvOp == Hexagon::V6_vconv_sf_qf32) ? Hexagon::V6_vsub_sf
633 : Hexagon::V6_vsub_hf;
635 Register SrcOp2Reg = SrcOp2.getReg();
645 if (!SrcOp2.isKill())
646 insertIEEEToQF(&*(++
MI->getIterator()), SrcOp2.getReg(), SrcOp2);
651 if (Pair.first ==
true && Pair.second ==
true) {
652 auto finalOpcode = getreplacedQFOpcode(SrcOpcode,
true,
true);
660 }
else if (Pair.first ==
true && Pair.second ==
false) {
661 auto finalOpcode = getreplacedQFOpcode(SrcOpcode,
true,
false);
665 if (SrcOpcode == Hexagon::V6_vmpy_qf32) {
666 Register SrcOp2Reg = SrcOp2.getReg();
677 if (!SrcOp2.isKill())
678 insertIEEEToQF(&*(++
MI->getIterator()), SrcOp2.getReg(), SrcOp2,
683 }
else if (finalOpcode == Hexagon::V6_vadd_qf16_mix ||
684 finalOpcode == Hexagon::V6_vadd_qf32_mix ||
685 finalOpcode == Hexagon::V6_vmpy_qf16_mix_hf ||
686 finalOpcode == Hexagon::V6_vmpy_qf32_mix_hf) {
696 }
else if ((SrcOpcode == Hexagon::V6_vsub_qf32 ||
697 SrcOpcode == Hexagon::V6_vsub_qf16) &&
699 Changed |= HandleSub(SrcOpcode);
709 }
else if (Pair.first ==
false && Pair.second ==
true) {
711 auto finalOpcode = getreplacedQFOpcode(SrcOpcode,
false,
true);
714 if (SrcOpcode == Hexagon::V6_vmpy_qf32) {
715 Register SrcOp1Reg = SrcOp1.getReg();
728 if (!SrcOp1.isKill())
729 insertIEEEToQF(&*(++
MI->getIterator()), SrcOp1.getReg(), SrcOp1,
744 eraseList.push_back(
MI);
748 for (MachineInstr *delMI : eraseList)
749 QFUsesMap.erase(delMI);
755void HexagonPostRAHandleQFP::insertInstr(MachineInstr *
MI,
unsigned MIOpcode,
756 unsigned SrcReg,
unsigned DstReg,
759 MachineInstrBuilder MIB;
760 MachineBasicBlock *
MBB =
MI->getParent();
763 auto MINext = ++
MI->getIterator();
767 MIB =
BuildMI(*
MBB, MINext,
DL, HII->get(MIOpcode), DstReg)
775MCPhysReg HexagonPostRAHandleQFP::findAllocatableReg(MachineInstr *
MI)
const {
776 LLVM_DEBUG(
dbgs() <<
"\tUsing V30 register to store a vector of zeroes!");
781bool HexagonPostRAHandleQFP::HandleNonSatInstr() {
783 for (
auto It : QFNonSatMIs) {
784 MachineInstr *
MI = It.first;
785 auto MIOpcode =
MI->getOpcode();
786 auto Op =
MI->getOperand(1);
791 if (MIOpcode == Hexagon::V6_vconv_hf_qf16 ||
792 MIOpcode == Hexagon::V6_vconv_f8_qf16) {
794 insertIEEEToQF(
MI, DefReg,
Op);
798 insertInstr(
MI, Hexagon::V6_vconv_hf_qf16, DefReg, DefReg,
803 }
else if (MIOpcode == Hexagon::V6_vconv_hf_qf32 ||
804 MIOpcode == Hexagon::V6_vconv_bf_qf32) {
805 Register DefLo = HRI->getSubReg(DefReg, Hexagon::vsub_lo);
806 Register DefHi = HRI->getSubReg(DefReg, Hexagon::vsub_hi);
808 if (It.second == ConvOperand::HiLo) {
809 insertIEEEToQF(
MI, DefLo,
Op,
true );
810 insertIEEEToQF(
MI, DefHi,
Op,
true );
814 auto KillState = SubRegKillSet[
MI];
815 if (!KillState.first)
816 insertInstr(
MI, Hexagon::V6_vconv_sf_qf32, DefHi, DefHi,
819 if (!KillState.second)
820 insertInstr(
MI, Hexagon::V6_vconv_sf_qf32, DefLo, DefLo,
823 }
else if (It.second == ConvOperand::Hi) {
824 insertIEEEToQF(
MI, DefHi,
Op,
true );
826 insertInstr(
MI, Hexagon::V6_vconv_sf_qf32, DefHi, DefHi,
830 insertIEEEToQF(
MI, DefLo,
Op,
true );
832 insertInstr(
MI, Hexagon::V6_vconv_sf_qf32, DefLo, DefLo,
836 }
else if (MIOpcode == Hexagon::V6_vconv_sf_qf32) {
837 insertIEEEToQF(
MI, DefReg,
Op,
true );
839 insertInstr(
MI, Hexagon::V6_vconv_sf_qf32, DefReg, DefReg,
847 if (QFNonSatMIs.empty())
855void HexagonPostRAHandleQFP::collectLivenessForSubregs(
856 NodeAddr<UseNode *> &UsedNode) {
857 RegisterRef UR = UsedNode.
Addr->getRegRef(*DFG);
858 NodeAddr<StmtNode *> UseStmt = UsedNode.
Addr->getOwner(*DFG);
859 MachineInstr *UseInstr = UseStmt.
Addr->getCode();
861 Register UseDefLo = HRI->getSubReg(UseOp.getReg(), Hexagon::vsub_lo);
862 Register UseDefHi = HRI->getSubReg(UseOp.getReg(), Hexagon::vsub_hi);
865 bool isHiSubRegKilled =
true, isLoSubRegKilled =
true;
871 for (
auto RD :
P.first) {
872 NodeAddr<DefNode *> RegDef = DFG->
addr<DefNode *>(RD);
876 NodeAddr<StmtNode *> RegStmt = RegDef.Addr->getOwner(*DFG);
877 MachineInstr *ReachDefInstr = RegStmt.
Addr->getCode();
878 if (ReachDefInstr ==
nullptr)
884 if (Hexagon::HvxWRRegClass.
contains(DefReg)) {
886 isHiSubRegKilled = isLoSubRegKilled =
false;
896 for (
auto UIntr : UseSet) {
897 NodeAddr<UseNode *> UA = DFG->
addr<UseNode *>(UIntr);
898 NodeAddr<StmtNode *> UseStmt = UA.
Addr->getOwner(*DFG);
899 MachineInstr *
UseMI = UseStmt.Addr->getCode();
900 if (
UseMI ==
nullptr)
904 if (
UseMI == UseInstr)
907 isLoSubRegKilled =
false;
911 isHiSubRegKilled =
false;
917 SubRegKillSet[UseInstr] = std::make_pair(isHiSubRegKilled, isLoSubRegKilled);
921void HexagonPostRAHandleQFP::collectQFPStackRefill(
922 NodeAddr<StmtNode *> *StNode) {
923 NodeAddr<DefNode *> DfNode =
924 StNode->
Addr->members_if(DFG->
IsDef, *DFG).front();
925 MachineInstr *
MI = StNode->
Addr->getCode();
927 const MachineOperand &OpFI =
MI->getOperand(1);
932 RefillMIs.push_back(DfNode);
937void HexagonPostRAHandleQFP::collectConvQFInstr(NodeAddr<DefNode *> &RegDef) {
940 NodeAddr<StmtNode *> DefStmt = RegDef.
Addr->getOwner(*DFG);
941 MachineInstr *DefInstr = DefStmt.
Addr->getCode();
943 for (
auto UI : UseSet) {
944 NodeAddr<UseNode *> UA = DFG->
addr<UseNode *>(UI);
947 NodeAddr<StmtNode *> UseStmt = UA.
Addr->getOwner(*DFG);
948 MachineInstr *QFConvInstr = UseStmt.
Addr->getCode();
959 collectLivenessForSubregs(UA);
960 unsigned Op = ConvOperand::Undefined;
961 if (QFNonSatMIs.contains(QFConvInstr))
962 Op = QFNonSatMIs[QFConvInstr];
965 if (Hexagon::HvxWRRegClass.
contains(DefReg))
966 Op = ConvOperand::HiLo;
968 else if (DefReg == HRI->getSubReg(
UseReg, Hexagon::vsub_lo))
969 Op |= ConvOperand::Lo;
972 Op |= ConvOperand::Hi;
973 QFNonSatMIs[QFConvInstr] =
Op;
975 QFNonSatMIs[QFConvInstr] = ConvOperand::HiLo;
977 IgnoreInsertConvList.insert(DefInstr);
978 LLVM_DEBUG(std::string OpType =
"";
switch (QFNonSatMIs[QFConvInstr]) {
979 case ConvOperand::HiLo:
982 case ConvOperand::Lo:
985 case ConvOperand::Hi:
989 OpType =
"Undefined";
990 }
dbgs() <<
"Collecting convert instruction with type "
992 QFConvInstr->dump());
1000void HexagonPostRAHandleQFP::collectCopies(NodeAddr<StmtNode *> *StNode) {
1002 NodeAddr<DefNode *> CopyDef =
1003 StNode->
Addr->members_if(DFG->
IsDef, *DFG).front();
1004 MachineInstr *CopyInstr = StNode->
Addr->getCode();
1007 for (NodeAddr<UseNode *> UA : StNode->
Addr->members_if(DFG->
IsUse, *DFG)) {
1008 RegisterRef UR = UA.
Addr->getRegRef(*DFG);
1013 dbgs() <<
"*** Unable to collect all reaching defs for use ***\n"
1014 << PrintNode<UseNode *>(UA, *DFG) <<
'\n';
1020 for (
auto RD :
P.first) {
1021 NodeAddr<DefNode *> RegDef = DFG->
addr<DefNode *>(RD);
1025 NodeAddr<StmtNode *> RegStmt = RegDef.
Addr->getOwner(*DFG);
1026 MachineInstr *ReachDefInstr = RegStmt.
Addr->getCode();
1027 if (ReachDefInstr ==
nullptr)
1032 if (ReachDefInstr->
getOpcode() == TargetOpcode::COPY) {
1033 auto pairKey = std::make_pair(CopyDef, RegDef);
1034 QFCopys[pairKey] = RegType::ieee;
1040 auto RegT = RegType::undefined;
1046 if (Hexagon::HvxWRRegClass.
contains(
1048 RegT = RegType::qf32_double;
1050 RegT = RegType::qf32;
1053 if (Hexagon::HvxWRRegClass.
contains(
1055 RegT = RegType::qf16_double;
1057 RegT = RegType::qf16;
1063 if (Hexagon::HvxWRRegClass.
contains(CopyReg) ||
1064 Hexagon::HvxVRRegClass.
contains(CopyReg))
1065 RegT = RegType::ieee;
1069 auto pairKey = std::make_pair(CopyDef, RegDef);
1070 QFCopys[pairKey] = RegT;
1077void HexagonPostRAHandleQFP::collectQFPStackSpill(
1078 NodeAddr<StmtNode *> *StNode) {
1080 MachineInstr *
MI = StNode->
Addr->getCode();
1083 const MachineOperand &OpFI =
MI->getOperand(0);
1096 if (!
MI->getOperand(2).isReg())
1102 for (NodeAddr<UseNode *> UA : StNode->
Addr->members_if(DFG->
IsUse, *DFG)) {
1103 QFPDefNode = UA.
Addr->getReachingDef();
1106 NodeAddr<DefNode *> RegDef = DFG->
addr<DefNode *>(QFPDefNode);
1107 assert(QFPDefNode != 0 &&
"Reaching def computation error");
1108 NodeAddr<StmtNode *> RegStmt = RegDef.
Addr->getOwner(*DFG);
1109 MachineInstr *ReachDefInstr = RegStmt.
Addr->getCode();
1110 if (ReachDefInstr ==
nullptr)
1113 ReachDefInstr->
dump());
1121 auto RR = RegDef.
Addr->getRegRef(*DFG).Id;
1126 dbgs() <<
"The corresponding XQF instruction is:\n";
1127 ReachDefInstr->
dump());
1130 SpillMIs.push_back(std::make_pair(
MI, RegDef));
1136void HexagonPostRAHandleQFP::collectQFUses(NodeAddr<DefNode *> RegDef,
1137 MachineInstr *
DefMI) {
1143 for (
auto UI : UseSet) {
1144 NodeAddr<UseNode *> UA = DFG->
addr<UseNode *>(UI);
1147 NodeAddr<StmtNode *> UseStmt = UA.
Addr->getOwner(*DFG);
1148 MachineInstr *
UseMI = UseStmt.
Addr->getCode();
1153 if (PossibleMultiReachDefs.count(UseStmt) == 0) {
1154 PossibleMultiReachDefs.insert(UseStmt);
1155 LLVM_DEBUG(
dbgs() <<
"\n[Collect instr with possible multidef]:";
1158 conditionallyInsert(*
UseMI, UsedReg);
1168bool HexagonPostRAHandleQFP::HandleMultiReachingDefs() {
1174 for (
auto It : PossibleMultiReachDefs) {
1178 auto Pair = QFUsesMap[
Instr];
1180 unsigned short UseNo = 1;
1182 for (NodeAddr<UseNode *> UA : It.Addr->members_if(DFG->
IsUse, *DFG)) {
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 = 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 = 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 = 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
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