bool HexagonSplitDoubleRegs::isProfitable(const USet &Part, LoopRegMap &IRM) const { unsigned FixedNum = 0, SplitNum = 0, LoopPhiNum = 0; int32_t TotalP = 0; for (unsigned DR : Part) { MachineInstr *DefI = MRI->getVRegDef(DR); int32_t P = profit(DefI); if (P == INT_MIN) return false; TotalP += P; // Reduce the profitability of splitting induction registers. if (isInduction(DR, IRM)) TotalP -= 30; for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end(); U != W; ++U) { MachineInstr *UseI = U->getParent(); if (isFixedInstr(UseI)) { FixedNum++; // Calculate the cost of generating REG_SEQUENCE instructions. for (auto &Op : UseI->operands()) { if (Op.isReg() && Part.count(Op.getReg())) if (Op.getSubReg()) TotalP -= 2; } continue; } // If a register from this partition is used in a fixed instruction, // and there is also a register in this partition that is used in // a loop phi node, then decrease the splitting profit as this can // confuse the modulo scheduler. if (UseI->isPHI()) { const MachineBasicBlock *PB = UseI->getParent(); const MachineLoop *L = MLI->getLoopFor(PB); if (L && L->getHeader() == PB) LoopPhiNum++; } // Splittable instruction. SplitNum++; int32_t P = profit(UseI); if (P == INT_MIN) return false; TotalP += P; } } if (FixedNum > 0 && LoopPhiNum > 0) TotalP -= 20*LoopPhiNum; DEBUG(dbgs() << "Partition profit: " << TotalP << '\n'); return TotalP > 0; }
void HexagonSplitDoubleRegs::partitionRegisters(UUSetMap &P2Rs) { typedef std::map<unsigned,unsigned> UUMap; typedef std::vector<unsigned> UVect; unsigned NumRegs = MRI->getNumVirtRegs(); BitVector DoubleRegs(NumRegs); for (unsigned i = 0; i < NumRegs; ++i) { unsigned R = TargetRegisterInfo::index2VirtReg(i); if (MRI->getRegClass(R) == DoubleRC) DoubleRegs.set(i); } BitVector FixedRegs(NumRegs); for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) { unsigned R = TargetRegisterInfo::index2VirtReg(x); MachineInstr *DefI = MRI->getVRegDef(R); // In some cases a register may exist, but never be defined or used. // It should never appear anywhere, but mark it as "fixed", just to be // safe. if (!DefI || isFixedInstr(DefI)) FixedRegs.set(x); } UUSetMap AssocMap; for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) { if (FixedRegs[x]) continue; unsigned R = TargetRegisterInfo::index2VirtReg(x); DEBUG(dbgs() << PrintReg(R, TRI) << " ~~"); USet &Asc = AssocMap[R]; for (auto U = MRI->use_nodbg_begin(R), Z = MRI->use_nodbg_end(); U != Z; ++U) { MachineOperand &Op = *U; MachineInstr *UseI = Op.getParent(); if (isFixedInstr(UseI)) continue; for (unsigned i = 0, n = UseI->getNumOperands(); i < n; ++i) { MachineOperand &MO = UseI->getOperand(i); // Skip non-registers or registers with subregisters. if (&MO == &Op || !MO.isReg() || MO.getSubReg()) continue; unsigned T = MO.getReg(); if (!TargetRegisterInfo::isVirtualRegister(T)) { FixedRegs.set(x); continue; } if (MRI->getRegClass(T) != DoubleRC) continue; unsigned u = TargetRegisterInfo::virtReg2Index(T); if (FixedRegs[u]) continue; DEBUG(dbgs() << ' ' << PrintReg(T, TRI)); Asc.insert(T); // Make it symmetric. AssocMap[T].insert(R); } } DEBUG(dbgs() << '\n'); } UUMap R2P; unsigned NextP = 1; USet Visited; for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) { unsigned R = TargetRegisterInfo::index2VirtReg(x); if (Visited.count(R)) continue; // Create a new partition for R. unsigned ThisP = FixedRegs[x] ? 0 : NextP++; UVect WorkQ; WorkQ.push_back(R); for (unsigned i = 0; i < WorkQ.size(); ++i) { unsigned T = WorkQ[i]; if (Visited.count(T)) continue; R2P[T] = ThisP; Visited.insert(T); // Add all registers associated with T. USet &Asc = AssocMap[T]; for (USet::iterator J = Asc.begin(), F = Asc.end(); J != F; ++J) WorkQ.push_back(*J); } } for (auto I : R2P) P2Rs[I.second].insert(I.first); }