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); } } }