Esempio n. 1
0
void ScheduleDAGInstrs::ComputeOperandLatency(SUnit *Def, SUnit *Use,
                                              SDep& dep) const {
  if (!InstrItins || InstrItins->isEmpty())
    return;

  // For a data dependency with a known register...
  if ((dep.getKind() != SDep::Data) || (dep.getReg() == 0))
    return;

  const unsigned Reg = dep.getReg();

  // ... find the definition of the register in the defining
  // instruction
  MachineInstr *DefMI = Def->getInstr();
  int DefIdx = DefMI->findRegisterDefOperandIdx(Reg);
  if (DefIdx != -1) {
    const MachineOperand &MO = DefMI->getOperand(DefIdx);
    if (MO.isReg() && MO.isImplicit() &&
        DefIdx >= (int)DefMI->getDesc().getNumOperands()) {
      // This is an implicit def, getOperandLatency() won't return the correct
      // latency. e.g.
      //   %D6<def>, %D7<def> = VLD1q16 %R2<kill>, 0, ..., %Q3<imp-def>
      //   %Q1<def> = VMULv8i16 %Q1<kill>, %Q3<kill>, ...
      // What we want is to compute latency between def of %D6/%D7 and use of
      // %Q3 instead.
      unsigned Op2 = DefMI->findRegisterDefOperandIdx(Reg, false, true, TRI);
      if (DefMI->getOperand(Op2).isReg())
        DefIdx = Op2;
    }
    MachineInstr *UseMI = Use->getInstr();
    // For all uses of the register, calculate the maxmimum latency
    int Latency = -1;
    if (UseMI) {
      for (unsigned i = 0, e = UseMI->getNumOperands(); i != e; ++i) {
        const MachineOperand &MO = UseMI->getOperand(i);
        if (!MO.isReg() || !MO.isUse())
          continue;
        unsigned MOReg = MO.getReg();
        if (MOReg != Reg)
          continue;

        int UseCycle = TII->getOperandLatency(InstrItins, DefMI, DefIdx,
                                              UseMI, i);
        Latency = std::max(Latency, UseCycle);
      }
    } else {
      // UseMI is null, then it must be a scheduling barrier.
      if (!InstrItins || InstrItins->isEmpty())
        return;
      unsigned DefClass = DefMI->getDesc().getSchedClass();
      Latency = InstrItins->getOperandCycle(DefClass, DefIdx);
    }

    // If we found a latency, then replace the existing dependence latency.
    if (Latency >= 0)
      dep.setLatency(Latency);
  }
}
/// \brief Perform target specific adjustments to the latency of a schedule
/// dependency.
void HexagonSubtarget::adjustSchedDependency(SUnit *Src, SUnit *Dst,
                                             SDep &Dep) const {
  MachineInstr *SrcInst = Src->getInstr();
  MachineInstr *DstInst = Dst->getInstr();
  if (!Src->isInstr() || !Dst->isInstr())
    return;

  const HexagonInstrInfo *QII = static_cast<const HexagonInstrInfo *>(getInstrInfo());

  // Instructions with .new operands have zero latency.
  if (QII->canExecuteInBundle(*SrcInst, *DstInst) &&
      isBestZeroLatency(Src, Dst, QII)) {
    Dep.setLatency(0);
    return;
  }

  if (!hasV60TOps())
    return;

  // Don't adjust the latency of post-increment part of the instruction.
  if (QII->isPostIncrement(*SrcInst) && Dep.isAssignedRegDep()) {
    if (SrcInst->mayStore())
      return;
    if (Dep.getReg() != SrcInst->getOperand(0).getReg())
      return;
  } else if (QII->isPostIncrement(*DstInst) && Dep.getKind() == SDep::Anti) {
    if (DstInst->mayStore())
      return;
    if (Dep.getReg() != DstInst->getOperand(0).getReg())
      return;
  } else if (QII->isPostIncrement(*DstInst) && DstInst->mayStore() &&
             Dep.isAssignedRegDep()) {
    MachineOperand &Op = DstInst->getOperand(DstInst->getNumOperands() - 1);
    if (Op.isReg() && Dep.getReg() != Op.getReg())
      return;
  }

  // Check if we need to change any the latency values when Phis are added.
  if (useBSBScheduling() && SrcInst->isPHI()) {
    changePhiLatency(*SrcInst, Dst, Dep);
    return;
  }

  // If it's a REG_SEQUENCE, use its destination instruction to determine
  // the correct latency.
  if (DstInst->isRegSequence() && Dst->NumSuccs == 1)
    DstInst = Dst->Succs[0].getSUnit()->getInstr();

  // Try to schedule uses near definitions to generate .cur.
  if (EnableDotCurSched && QII->isToBeScheduledASAP(*SrcInst, *DstInst) &&
      isBestZeroLatency(Src, Dst, QII)) {
    Dep.setLatency(0);
    return;
  }

  updateLatency(*SrcInst, *DstInst, Dep);
}
void ScheduleDAGInstrs::ComputeOperandLatency(SUnit *Def, SUnit *Use, 
                                              SDep& dep) const {
  const InstrItineraryData &InstrItins = TM.getInstrItineraryData();
  if (InstrItins.isEmpty())
    return;
  
  // For a data dependency with a known register...
  if ((dep.getKind() != SDep::Data) || (dep.getReg() == 0))
    return;

  const unsigned Reg = dep.getReg();

  // ... find the definition of the register in the defining
  // instruction
  MachineInstr *DefMI = Def->getInstr();
  int DefIdx = DefMI->findRegisterDefOperandIdx(Reg);
  if (DefIdx != -1) {
    int DefCycle = InstrItins.getOperandCycle(DefMI->getDesc().getSchedClass(),
                                              DefIdx);
    if (DefCycle >= 0) {
      MachineInstr *UseMI = Use->getInstr();
      const unsigned UseClass = UseMI->getDesc().getSchedClass();

      // For all uses of the register, calculate the maxmimum latency
      int Latency = -1;
      for (unsigned i = 0, e = UseMI->getNumOperands(); i != e; ++i) {
        const MachineOperand &MO = UseMI->getOperand(i);
        if (!MO.isReg() || !MO.isUse())
          continue;
        unsigned MOReg = MO.getReg();
        if (MOReg != Reg)
          continue;

        int UseCycle = InstrItins.getOperandCycle(UseClass, i);
        if (UseCycle >= 0)
          Latency = std::max(Latency, DefCycle - UseCycle + 1);
      }

      // If we found a latency, then replace the existing dependence latency.
      if (Latency >= 0)
        dep.setLatency(Latency);
    }
  }
}