예제 #1
0
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;
}
예제 #2
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);
}