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