USet Scr_Settings::Ports() { USet pp; if (!IsPortsValid(&pp)) pp.clear(); return pp; }
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 usetTests(USet &us, int n) { clock_t start, stop; cout << "Adding " << n << " elements..."; cout.flush(); start = clock(); for (int i = 0; i < n; i++) { us.add(rand() % (2*n)); } stop = clock(); cout << "done (" << ((double)(stop-start))/CLOCKS_PER_SEC << "s)" << endl; cout << "Finding " << n << " elements..."; cout.flush(); start = clock(); int success = 0; for (int i = 0; i < n; i++) { int z = rand() % (2*n); int y = us.find(z); if (y == z) success++; if (i % 300000 == 0) { cout << "[" << z << "=>" << y << "]"; } } stop = clock(); cout << "done [" << success << "/" << n << " (" << ((double)(stop-start))/CLOCKS_PER_SEC << "s)" << endl; cout << "Removing " << n << " elements..."; cout.flush(); start = clock(); for (int i = 0; i < n; i++) { us.remove(rand() % (2*n)); } stop = clock(); cout << "done (" << ((double)(stop-start))/CLOCKS_PER_SEC << "s)" << endl; cout << "Final size is " << us.size() << endl; cout << "Clearing " << us.size() << " elements..."; cout.flush(); start = clock(); us.clear(); stop = clock(); cout << "done (" << ((double)(stop-start))/CLOCKS_PER_SEC << "s)" << endl; }
void HexagonSplitDoubleRegs::collectIndRegsForLoop(const MachineLoop *L, USet &Rs) { const MachineBasicBlock *HB = L->getHeader(); const MachineBasicBlock *LB = L->getLoopLatch(); if (!HB || !LB) return; // Examine the latch branch. Expect it to be a conditional branch to // the header (either "br-cond header" or "br-cond exit; br header"). MachineBasicBlock *TB = 0, *FB = 0; MachineBasicBlock *TmpLB = const_cast<MachineBasicBlock*>(LB); SmallVector<MachineOperand,2> Cond; bool BadLB = TII->AnalyzeBranch(*TmpLB, TB, FB, Cond, false); // Only analyzable conditional branches. HII::AnalyzeBranch will put // the branch opcode as the first element of Cond, and the predicate // operand as the second. if (BadLB || Cond.size() != 2) return; // Only simple jump-conditional (with or without negation). if (!TII->PredOpcodeHasJMP_c(Cond[0].getImm())) return; // Must go to the header. if (TB != HB && FB != HB) return; assert(Cond[1].isReg() && "Unexpected Cond vector from AnalyzeBranch"); // Expect a predicate register. unsigned PR = Cond[1].getReg(); assert(MRI->getRegClass(PR) == &Hexagon::PredRegsRegClass); // Get the registers on which the loop controlling compare instruction // depends. unsigned CmpR1 = 0, CmpR2 = 0; const MachineInstr *CmpI = MRI->getVRegDef(PR); while (CmpI->getOpcode() == Hexagon::C2_not) CmpI = MRI->getVRegDef(CmpI->getOperand(1).getReg()); int Mask = 0, Val = 0; bool OkCI = TII->analyzeCompare(CmpI, CmpR1, CmpR2, Mask, Val); if (!OkCI) return; // Eliminate non-double input registers. if (CmpR1 && MRI->getRegClass(CmpR1) != DoubleRC) CmpR1 = 0; if (CmpR2 && MRI->getRegClass(CmpR2) != DoubleRC) CmpR2 = 0; if (!CmpR1 && !CmpR2) return; // Now examine the top of the loop: the phi nodes that could poten- // tially define loop induction registers. The registers defined by // such a phi node would be used in a 64-bit add, which then would // be used in the loop compare instruction. // Get the set of all double registers defined by phi nodes in the // loop header. typedef std::vector<unsigned> UVect; UVect DP; for (auto &MI : *HB) { if (!MI.isPHI()) break; const MachineOperand &MD = MI.getOperand(0); unsigned R = MD.getReg(); if (MRI->getRegClass(R) == DoubleRC) DP.push_back(R); } if (DP.empty()) return; auto NoIndOp = [this, CmpR1, CmpR2] (unsigned R) -> bool { for (auto I = MRI->use_nodbg_begin(R), E = MRI->use_nodbg_end(); I != E; ++I) { const MachineInstr *UseI = I->getParent(); if (UseI->getOpcode() != Hexagon::A2_addp) continue; // Get the output from the add. If it is one of the inputs to the // loop-controlling compare instruction, then R is likely an induc- // tion register. unsigned T = UseI->getOperand(0).getReg(); if (T == CmpR1 || T == CmpR2) return false; } return true; }; UVect::iterator End = std::remove_if(DP.begin(), DP.end(), NoIndOp); Rs.insert(DP.begin(), End); Rs.insert(CmpR1); Rs.insert(CmpR2); DEBUG({ dbgs() << "For loop at BB#" << HB->getNumber() << " ind regs: "; dump_partition(dbgs(), Rs, *TRI); dbgs() << '\n'; });
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); }