1414#ifndef LLVM_MC_MCSCHEDULE_H
1515#define LLVM_MC_MCSCHEDULE_H
1616
17- #include " llvm/Config/llvm-config.h"
18- #include " llvm/Support/DataTypes.h"
17+ #include " llvm/ADT/StringRef.h"
18+ #include " llvm/MC/MCInstrDesc.h"
19+ #include " llvm/Support/ErrorHandling.h"
1920#include < cassert>
21+ #include < optional>
2022
2123namespace llvm {
2224
@@ -25,6 +27,7 @@ struct InstrItinerary;
2527class MCSubtargetInfo ;
2628class MCInstrInfo ;
2729class MCInst ;
30+ class MCInstrDesc ;
2831class InstrItineraryData ;
2932
3033// / Define a kind of processor resource that will be modeled by the scheduler.
@@ -369,9 +372,19 @@ struct MCSchedModel {
369372 const MCSchedClassDesc &SCDesc);
370373
371374 int computeInstrLatency (const MCSubtargetInfo &STI, unsigned SClass) const ;
375+
372376 int computeInstrLatency (const MCSubtargetInfo &STI, const MCInstrInfo &MCII,
373377 const MCInst &Inst) const ;
374378
379+ template <typename MCSubtargetInfo, typename MCInstrInfo,
380+ typename InstrItineraryData, typename MCInstOrMachineInstr>
381+ int computeInstrLatency (
382+ const MCSubtargetInfo &STI, const MCInstrInfo &MCII,
383+ const MCInstOrMachineInstr &Inst,
384+ llvm::function_ref<const MCSchedClassDesc *(const MCSchedClassDesc *)>
385+ ResolveVariantSchedClass =
386+ [](const MCSchedClassDesc *SCDesc) { return SCDesc; }) const ;
387+
375388 // Returns the reciprocal throughput information from a MCSchedClassDesc.
376389 static double
377390 getReciprocalThroughput (const MCSubtargetInfo &STI,
@@ -393,6 +406,54 @@ struct MCSchedModel {
393406 static const MCSchedModel Default;
394407};
395408
409+ // The first three are only template'd arguments so we can get away with leaving
410+ // them as incomplete types below. The third is a template over
411+ // MCInst/MachineInstr so as to avoid a layering violation here that would make
412+ // the MC layer depend on CodeGen.
413+ template <typename MCSubtargetInfo, typename MCInstrInfo,
414+ typename InstrItineraryData, typename MCInstOrMachineInstr>
415+ int MCSchedModel::computeInstrLatency (
416+ const MCSubtargetInfo &STI, const MCInstrInfo &MCII,
417+ const MCInstOrMachineInstr &Inst,
418+ llvm::function_ref<const MCSchedClassDesc *(const MCSchedClassDesc *)>
419+ ResolveVariantSchedClass) const {
420+ static const int NoInformationAvailable = -1 ;
421+ // Check if we have a scheduling model for instructions.
422+ if (!hasInstrSchedModel ()) {
423+ // Try to fall back to the itinerary model if the scheduling model doesn't
424+ // have a scheduling table. Note the default does not have a table.
425+
426+ llvm::StringRef CPU = STI.getCPU ();
427+
428+ // Check if we have a CPU to get the itinerary information.
429+ if (CPU.empty ())
430+ return NoInformationAvailable;
431+
432+ // Get itinerary information.
433+ InstrItineraryData IID = STI.getInstrItineraryForCPU (CPU);
434+ // Get the scheduling class of the requested instruction.
435+ const MCInstrDesc &Desc = MCII.get (Inst.getOpcode ());
436+ unsigned SCClass = Desc.getSchedClass ();
437+
438+ unsigned Latency = 0 ;
439+
440+ for (unsigned Idx = 0 , IdxEnd = Inst.getNumOperands (); Idx != IdxEnd; ++Idx)
441+ if (std::optional<unsigned > OperCycle = IID.getOperandCycle (SCClass, Idx))
442+ Latency = std::max (Latency, *OperCycle);
443+
444+ return int (Latency);
445+ }
446+
447+ unsigned SchedClass = MCII.get (Inst.getOpcode ()).getSchedClass ();
448+ const MCSchedClassDesc *SCDesc = getSchedClassDesc (SchedClass);
449+ SCDesc = ResolveVariantSchedClass (SCDesc);
450+
451+ if (!SCDesc || !SCDesc->isValid ())
452+ return NoInformationAvailable;
453+
454+ return MCSchedModel::computeInstrLatency (STI, *SCDesc);
455+ }
456+
396457} // namespace llvm
397458
398459#endif
0 commit comments